Я пытаюсь понять C ++ 11 Rvalue ссылки и как использовать их для оптимальной производительности в моем коде.
Допустим, у нас есть класс A
у которого есть указатель на большое количество динамически размещаемых данных.
Кроме того, метод foo(const A& a)
что-то делает с объектом класса A
,
я бы хотел предотвратить конструктор копирования A
от того, чтобы называться когда объект A
передается в функцию foo
, так как в этом случае он будет выполнять глубокое копирование лежащих в основе данных кучи.
Я проверил прохождение ссылки на lvalue:
A a;
foo(a);
и передача rvalue ссылки:
foo(A());
В обоих случаях конструктор копирования был не называется.
Это ожидается или это связано с некоторой оптимизацией моего компилятора (Apple LLVM 5.1)? Есть ли какие-либо спецификации по этому поводу?
Это ожидается. Если вы передадите аргумент параметру ссылочного типа (будь то lvalue или rvalue ссылка), объект не будет скопирован. Вот и весь смысл ссылок.
Путаница у вас довольно распространенная. Выбор конструктора копирования или перемещения происходит только при передаче объекта по значению. Например:
void foo(A a);
При прохождении A
В зависимости от этой функции компилятор определит, использовать ли конструктор копирования или перемещения, в зависимости от того, является ли передаваемое вами выражение выражением lvalue или rvalue.
С другой стороны, ни одна из следующих функций даже не будет пытаться вызвать конструктор копирования или перемещения, потому что ни один объект не строится:
void foo(A& a);
void foo(const A& a);
void foo(A&& a);
void foo(const A&& a);
Важно отметить, что у вас редко (если вообще когда-либо) должна быть какая-либо причина написать функцию, кроме конструктора перемещения / оператора присваивания, которая принимает ссылку на значение. Вы должны выбирать между передачей по значению и передачей по const
lvalue ссылка:
Если вам все равно понадобится копия объекта внутри функции (возможно, из-за того, что вы хотите изменить копию или передать ее другой функции), возьмите ее по значению (A
). Таким образом, если вам дано значение lvalue, его нужно будет скопировать (вы не можете избежать этого), но если вы получите значение r, оно будет оптимально перенесено в вашу функцию.
Если вам не нужна копия объекта, возьмите ее с const
lvalue ссылка (const A&
). Таким образом, независимо от того, получили ли вы значение lvalue или rvalue, копия не будет создана. Вы не должны использовать это, когда вам действительно нужно скопировать это, потому что это мешает вам использовать семантику перемещения.
Судя по всему, вы не собираетесь делать никаких копий, так что const A&
параметр будет работать.