【问题标题】:Passing rvalue reference to const lvalue reference paremeter将右值引用传递给 const 右值引用参数
【发布时间】:2014-09-09 18:33:05
【问题描述】:

我正在尝试了解 C++11 右值引用以及如何在我的代码中使用它们来获得最佳性能。

假设我们有一个类A,它有一个指向大量动态分配数据的成员指针。

此外,一个方法 foo(const A& a)A 类的对象执行某些操作。

A 的对象被传递给函数foo 时,我想防止调用A 的复制构造函数,因为在这种情况下它将执行深层复制底层堆数据。

我测试了传递左值引用:

    A a;
    foo(a);

并传递一个右值引用:

    foo(A());

在这两种情况下,复制构造函数都没有被调用。

这是预期的还是由于我的编译器(Apple LLVM 5.1)的一些优化?有这方面的规范吗?

【问题讨论】:

    标签: c++ c++11 lvalue rvalue const-reference


    【解决方案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 左值引用传递之间做出决定:

      1234563这样,如果给你一个左值,它必须被复制(你无法避免这种情况),但如果你给了一个右值,它会被最佳地移动到你的函数中。
    1. 如果您不需要对象的副本,请通过 const 左值引用 (const A&) 获取它。这样,无论您获得的是左值还是右值,都不会发生复制。但是,当您确实需要复制它时,您不应该使用它,因为它会阻止您使用移动语义。

    从它的声音来看,您根本不会制作任何副本,因此const A& 参数会起作用。

    【讨论】:

    • 我只批准了starius'的编辑并对其进行了微不足道的更改;重要的是他的编辑。应该有办法让原始编辑的名字出现在这样的变化上。
    • @bogdan 它显示你是因为你是最后一个编辑的人,但 starius 在编辑列表中(如果你点击文本“1 小时前编辑”)。
    • 是的,我看到了,但仍然......如果我知道我的“改进”将作为单独的编辑出现,我会保留原来的更改。最初我并没有过多考虑版本控制。回想起来,很清楚为什么它会以这种方式工作——它将两个更改联系起来,但没有合并它们。无论如何,抱歉打扰了。
    • 想象我们有一个类 X,包含一个向量。 MyClass 包含大量堆内存数据。现在,如果我为 X 类编写一个函数add,我认为右值引用参数是必要的。 x.add(MyClass(...)) 将调用该函数。
    • 这样,如果给你一个左值,它必须被复制(你无法避免这种情况),但如果你给了一个右值,它会以最佳方式移动到您的函数中。 - 如果函数接受 A 类型的参数,并且我将其传递给 A&& 类型的右值,那么该函数将如何编译,以及如何以最佳方式移动?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-05
    • 1970-01-01
    • 1970-01-01
    • 2018-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多