如何在没有副本的情况下使右值引用传递的对象保持活动状态?

How to keep object passed by rvalue reference alive without copy?

我正在尝试将 Child 作为右值传递给 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; }
};

输出为:

Child: created
Parent: created
Child: destroyed
------Done------
Parent: destroyed

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

问题 1:为什么 Child 没有在最后(或至少在 完成 之后)销毁?
问题二:如何让它长寿?

P.S:

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

给出完全相同的结果。

你引用的部分标准是这样的:

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

现在 a 将在函数范围 main 结束后被销毁。这不适用于 class 成员。通过引用将值传递给函数(毕竟构造函数只是一个函数)不会延长引用的生命周期。也不会将其分配给成员变量。

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

你遗漏了那句话的重要部分。更准确的引用是:"Rvalue references can be used to extend the lifetimes of temporary objects".

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

  • a temporary bound to a reference member in a constructor initializer list persists only until the constructor exits, not as long as the object exists. (note: such initialization is ill-formed as of DR 1696).

您将临时变量绑定到构造函数初始化列表中的引用成员。临时的生命周期不会超出构造函数的末尾。在调用对象的析构函数之前销毁临时文件。


如何让它长寿?这变得棘手,但如果参数始终是临时参数,则可以使您的成员成为成员的 non-reference 和 move 参数。如果您想要更大的灵活性,您可能需要接受一些复制。