среда, 3 апреля 2019 г.

Пример с использованием r-value ссылок в С++


Данный пример иллюстрирует проблему и ее решение.

Допустим, нам необходимо реализовать операции сложения и присваивания для некоторого объекта. Мы не можем использовать в качестве параметров ссылки на константу, поскольку при выполнении операций внутри каждого объекта меняет свое значение итератор. Операция сложения должна возвращать объект, созданный в стеке внутри функции. Но тогда на вход присваивания пойдет ссылка на временный объект, размещенный в стеке, что не разрешит использовать const Object& в качестве параметра присваивания. Выходом из ситуации является использование r-value ссылки.

#include <cstring>
#include <utility>
using namespace std;
const int size=10;
class Object
{
private:
  int data[size];
  int iter;     // моделируем использование итератора внутри объекта
public:
  Object(int val) :iter{ 0 } { 
    for (iter = 0; iter < size; ++iter)
      data[iter] = val;
    iter = 0;
  }
  // здесь приходится использовать ссылку на временный объект в стеке
  Object& operator=(Object&& obj) { 
    for (iter = 0, obj.iter = 0; iter < size; ++iter, ++obj.iter)
      data[iter] = obj.data[obj.iter];
    iter = 0;
    obj.iter = 0;
    return *this;
  }
  Object(Object& obj) {   // нельзя использовать ссылку на константу!
    for (iter = 0, obj.iter = 0; iter < size; ++iter, ++obj.iter)
      data[iter] = obj.data[obj.iter];
    iter = 0;
    obj.iter = 0;
  }
  Object operator+(Object& obj) {  // нельзя использовать ссылку на константу!
    Object result(0);
    for (iter = 0, obj.iter = 0; iter < size; ++iter, ++obj.iter)
      result.data[iter] = data[iter]+obj.data[obj.iter];
      iter = 0;
      obj.iter = 0;
      return result;  // возвращаем объект, копируя его через стек
  }
};

int main()
{
  Object a{ 1 }, b{ 2 }, c{ 0 };
  c = a + b;
  return 0;
}

Комментариев нет:

Отправить комментарий