c++ - 创建对象,局部变量与右值引用

标签 c++ rvalue-reference

在创建对象时使用 r 值引用有什么好处,否则它会在普通的局部变量中?

Foo&& cn = Foo();
cn.m_flag = 1;
bar.m_foo = std::move(cn);
//cn is not used again

Foo cn;
cn.m_flag = 1;
bar.m_foo = std::move(cn); //Is it ok to move a non rvalue reference?
//cn is not used again

在第一个代码片段中,显然不会有任何拷贝,但我猜在第二个代码片段中编译会优化拷贝?

同样在第一个片段中,对象实际存储在内存中的哪个位置(在第二个片段中,它存储在封闭函数的堆栈帧中)?

最佳答案

这些代码片段大多是等价的。这个:

Foo&& rf = Foo();

将临时对象绑定(bind)到引用,从而将临时对象的生命周期延长到引用的生命周期。 Foo 只有在 rf 超出范围时才会被销毁。这与您得到的行为相同:

Foo f;

除了在后一个示例中 f 是默认初始化的,但在前一个示例中 rf 是值初始化的。对于某些类型,两者是等价的。对于其他人,他们不是。如果您改为编写 Foo f{},那么这种差异就会消失。

剩下的一个区别与复制省略有关:

Foo give_a_foo_rv() {
    Foo&& rf = Foo();
    return rf;
}

Foo give_a_foo() {
    Foo f{};
    return f;
}

第一个例子中不允许执行RVO,因为rfgive_a_foo_rv()的返回类型不一样。此外, rf 甚至不会被自动移动到返回类型中,因为它不是一个对象,所以它没有自动存储持续时间,所以这是一个额外的拷贝(直到 C++20,其中这是一个额外的 Action ):

Foo f = give_a_foo_rv(); // a copy happens here!
Foo g = give_a_foo();    // no move or copy

it seems clear that there will not be any copies

这完全取决于移动 Foo 的实际作用。如果 Foo 看起来像:

struct Foo {
    Foo() = default;
    Foo(Foo const& ) = default;
    Foo& operator=(Foo const& ) = default;

    // some members
};

然后移动 Foo 仍然会复制。


是的,在第二个示例中使用 std::move(f) 是完全可以的。您不需要从 Tmove 的右值引用类型的对象。这将严重限制移动的实用性。

关于c++ - 创建对象,局部变量与右值引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39370191/

相关文章:

c++ - 了解右值引用

c++ - 模板构造函数意外触发移动构造函数(std::function 和 mini case)

c++ - Rcpp 中用户编写的 header /命名空间中的函数声明

c++ - 使用 *this 从右值进行预期的无效初始化

c++ - 是否可以在不进行类型推导的情况下实现类似转发引用的行为?

c++ - std::function 可以从右值引用移动构造到临时仿函数对象吗?

c++ - 在opencv中读取视频文件的连续图像

c++ - 返回语句是否被视为跳转指令?

c++ - 函数声明中带有 [ ] 运算符的指针 - 这是什么意思?

c++ - 吃 bean 游戏的东西没有申报?