将右值引用传递给常量左值引用参数 [英] Passing rvalue reference to const lvalue reference paremeter

查看:361
本文介绍了将右值引用传递给常量左值引用参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试理解C ++ 11 rvalue引用,以及如何在我的代码中使用它们以实现最佳性能。

I am trying to understand C++11 rvalue references and how to use them for optimal performance in my code.

让我们说我们有一个 A 类,该类的成员指针指向大量动态分配的数据。

Let's say we have a class A that has a member pointer to a large amount of dynamically allocated data.

此外,方法 foo(const A& a)对类 A 的对象进行处理。

Furthermore, a method foo(const A& a) that does something with an object of class A.

我想防止 A 被调用 > A 传递给函数 foo ,因为在这种情况下,它将执行基础堆数据的深层副本。

I want to prevent the copy constructor of A from being called when an object of A is passed to the function foo, since in that case it will perform a deep copy of the underlying heap data.

我测试了传递左值引用:

I tested passing an lvalue reference:

    A a;
    foo(a);

并传递右值引用:

    foo(A());

在这两种情况下,都不会调用 复制构造函数。

In both cases the copy constructor was not called.

这是预期的还是由于我的编译器(Apple LLVM 5.1)进行了一些优化?对此有任何规范吗?

Is this expected or is this due to some optimization of my compiler (Apple LLVM 5.1)? Is there any specification about this?

推荐答案

这是预期的。如果将参数传递给引用类型参数(左值引用或右值引用),则不会复制该对象。

That is expected. If you pass an argument to a reference type parameter (whether lvalue or rvalue reference), the object will not be copied. That is the whole point of references.

您所遇到的困惑非常普遍。复制或移动构造函数的选择仅在按值传递对象时发生。例如:

The confusion you're having is pretty common. The choice of copy or move constructor only occurs when passing an object by value. For example:

void foo(A a);

A 对象传递给此函数时,则编译器将根据您传递的表达式是左值表达式还是右值表达式来确定是使用copy还是move构造函数。

When passing an A object to this function, the compiler will determine whether to use the copy or move constructor depending on whether the expression you pass is an lvalue or rvalue expression.

以下函数甚至会尝试调用复制或移动构造函数,因为没有构造对象

On the other hand, none of the following functions would even try to invoke the copy or move constructor because no object is being constructed:

void foo(A& a);
void foo(const A& a);
void foo(A&& a);
void foo(const A&& a);

重要的是要注意,很少(如果有的话)应该没有任何理由来编写函数,其他而不是采用右值引用的move构造函数/赋值运算符。您应该在按值传递和按 const 左值引用传递之间进行选择:

It's important to note that you should rarely (if ever) have any reason to write a function, other than a move constructor/assignment operator, that takes an rvalue reference. You should be deciding between passing by value and passing by const lvalue reference:


  1. 如果您仍然需要在函数内复制对象(也许是因为您想要修改副本或将其传递给另一个函数),请按值( A )。这样,如果给定左值,则必须将其复制(无法避免),但是如果给定右值,则将其最佳地移入函数中。

  1. If you're going to need a copy of the object inside the function anyway (perhaps because you want to modify a copy or pass it to another function), take it by value (A). This way, if you're given an lvalue, it'll have to be copied (you can't avoid this), but if you're given an rvalue, it'll be optimally moved into your function.

如果您不需要该对象的副本,请通过 const 左值引用( const A& )。这样,无论您获得的是左值还是右值,都不会进行复制。不过,当您确实需要复制它时,则不应使用它,因为它会阻止您利用移动语义。

If you're not going to need a copy of the object, take it by const lvalue reference (const A&). This way, regardless of whether you're given an lvalue or rvalue, no copy will take place. You shouldn't use this when you do need to copy it though, because it prevents you from utilising move semantics.

从声音上讲,您根本不会制作任何副本,因此 const A& 参数将起作用。

From the sounds of it, you're not going to make any copies at all, so a const A& parameter would work.

这篇关于将右值引用传递给常量左值引用参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆