我正在尝试理解 C++11 右值引用 以及如何在我的代码中使用它们来实现最佳性能。
假设我们有一个类 A
,它有一个指向大量动态分配数据的成员指针。
此外,一个方法 foo(const A& a)
对类 A
的对象执行某些操作。
当 A
的对象被传递给函数 foo 时,我想阻止
,因为在这种情况下,它将执行底层堆数据的深层复制。A
的复制构造函数被调用
我测试了传递一个左值引用:
A a;
foo(a);
并传递一个右值引用:
foo(A());
在这两种情况下,复制构造函数都没有被调用。
这是预期的还是由于我的编译器(Apple LLVM 5.1)的一些优化?有没有这方面的规范?
最佳答案
这是意料之中的。如果将参数传递给引用类型参数(无论是左值还是右值引用),则不会复制该对象。这就是整个引用点。
您遇到的困惑很常见。只有在按值传递对象时才会选择复制或移动构造函数。例如:
void foo(A a);
当传递一个A
对象给这个函数时,编译器会根据你传递的表达式是左值表达式还是右值表达式来决定是使用复制构造函数还是移动构造函数。
另一方面,以下函数甚至都不会尝试调用复制或移动构造函数,因为没有对象正在构造:
void foo(A& a);
void foo(const A& a);
void foo(A&& a);
void foo(const A&& a);
重要的是要注意,除了移动构造函数/赋值运算符之外,您应该很少(如果有的话)有任何理由编写采用右值引用的函数。您应该在按值传递和按 const
左值引用传递之间做出决定:
如果您无论如何都需要函数内部对象的拷贝(可能是因为您想修改拷贝或将其传递给另一个函数),请按值获取它 (
A
)。这样,如果您获得了一个左值,则必须复制它(您无法避免这种情况),但如果您获得了一个右值,它将被最佳地移动到您的函数中。如果您不需要对象的拷贝,请通过
const
左值引用 (const A&
) 获取它。这样,无论您获得的是左值还是右值,都不会发生复制。不过,当您确实需要复制它时,您不应该使用它,因为它会阻止您使用移动语义。
从它的声音来看,您根本不会制作任何拷贝,因此 const A&
参数会起作用。
关于c++ - 将右值引用传递给 const 左值引用参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24828074/