gpt4 book ai didi

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

转载 作者:IT老高 更新时间:2023-10-28 23:18:41 25 4
gpt4 key购买 nike

在创建对象时使用 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com