如何通过右值引用传递的对象保持活动状态而无需复制?

时间:2019-07-06 17:58:35

标签: c++ c++11 pass-by-reference rvalue-reference

我正在尝试将Child作为r值传递给Parent,并保存在其中,不复制Child

Parent p{ Child{} };

cout << "----Done----" << endl;

现在执行:

class Child
{
public:
    Child() { cout << "Child: created" << endl; }

    ~Child() { cout << "Child: destroyed" << endl; }
};

class Parent
{
    // store as r-value ref
    Child&& child;

public:
    // pass by r-value ref and move
    Parent(Child&& c) :child(move(c))
    {
        cout << "Parent: created" << endl;
    }

    ~Parent() { cout << "Parent: destroyed" << endl; }
};

输出为:

  

孩子:已创建
  父级:已创建
  孩子:被摧毁
  ------完成------
  父母:被摧毁

cppref说:Rvalue references can be used to extend the lifetimes of temporary objects

问题1:Child为什么在最后(或至少在完成之后)没有被销毁?
问题2:如何使其使用寿命更长?

PS:

Child& child;
...
Parent(Child c) :child(c)

给出完全相同的结果。

2 个答案:

答案 0 :(得分:1)

  

cppref说:Rvalue references can be used to extend the lifetimes of temporary objects

您忽略了该报价的重要部分。更准确的引用是:“右值引用可用于extend the lifetimes临时对象”

注意区别吗? (如果您不这样做,请不要太担心,因为它很微妙。)有一个链接可以解释如何以及何时可以延长临时期限。您已将此问题标记为C ++ 11,因此要点在C ++ 14生效之前一直有效:

  
      
  • 绑定到构造函数初始化器列表中的引用成员的临时绑定仅持续到构造函数退出之前,而不存在该对象存在的时间。 (请注意:此类初始化从DR 1696开始是错误的)。
  •   

您将临时对象绑定到构造函数初始化器列表中的引用成员。临时对象的寿命不会超出构造函数的末尾。在调用对象的析构函数之前,临时对象已被销毁。


如何使其寿命更长?这很棘手,但是如果参数始终是临时的,则可以使成员成为非引用,并将参数move赋予成员。如果需要更大的灵活性,则可能需要接受一些复制。

答案 1 :(得分:0)

您引用的部分标准涉及以下内容:

struct A { };
int main() {
  const A &a = A{};
  ...
}

,一旦功能a的作用域结束,main现在将被销毁。这不适用于班级成员。通过引用将值传递给函数(毕竟构造函数只是一个函数)不会扩展引用的生命周期。也不会将其分配给成员变量。