在下面的 C++11+ 代码中,应该优先选择哪种 return 语句构造方式?
#include <utility>
struct Bar
{
};
struct Foo
{
Bar bar;
Bar get() &&
{
return std::move(bar); // 1
return bar; // 2
}
};
在下面的 C++11+ 代码中,应该优先选择哪种 return 语句构造方式?
#include <utility>
struct Bar
{
};
struct Foo
{
Bar bar;
Bar get() &&
{
return std::move(bar); // 1
return bar; // 2
}
};
既然这是一个r-value引用的成员函数,this
很可能即将过期。因此,假设Bar
从移动中获益,移动bar
是有意义的。
由于bar
是一个成员变量,而不是本地对象/函数参数,在返回语句中进行副本省略的常规标准并不适用。除非你明确使用std::move
,否则它总是会复制。
所以我的答案是选择选项一。
&
和 const &
添加重载。 - sbabbiBar&& get() &&
// ^^
{
return std::move(bar);
}
另外,顺便一提:
Bar& get() & { return bar; }
Bar const& get() const& { return bar; }
Bar const&& get() const&& { return std::move(bar); }
bar
进行 move
是正确的。但仅仅因为我们可以移动 bar
并不意味着我们必须强制这样做并产生额外的操作,因此我们应该返回一个右值引用。std::optional<T>::value
。for (auto e : Foo{}.get()) { /* ... */ }
这样的事情来说太危险了,不是吗? - Constructorget()
函数并且其有益处的情况是.get().somethingImmediatelyHere()
,因为这里会避免移动。对于其他情况,auto f = .get();
您的函数也将有一个移动操作。 - Johannes Schaub - litbFoo
实例上调用此方法,调用者的意图包括创建一个新的 Bar
值。例如:Foo Produce_Foo(void);
// Alright, caller wanted to make a new `Bar` value, and by using `move`
// we've avoided a heavy copy operation.
auto bar{Produce_Foo().get()};
// Oops! No one asked us to make a useless temporary...
cout << Produce_Foo().get().value() << endl;
Bar const & get_bar() const noexcept
{
return bar;
}
// no particular need to this method to be r-value reference qualified
// because there is no direct correlation between Foo instance being moved / temp
// and intention to take control over content of stored bar object.
Bar give_bar() noexcept
{
return ::std::move(bar);
}
现在用户有选择了,就不会再出现问题:
// Alright, caller wanted to make a new `Bar` value, and by using `move`
// we've avoided a heavy copy operation.
// There is also no need to figure out whether Produce_Foo returned an rvalue or not.
auto bar{Produce_Foo().give_bar()};
// Alright, no extra temporaries.
cout << Produce_Foo().get_bar().value() << endl;
Produce_Foo().get().value()
的问题仅仅在于当不必要时通过移动构造函数创建了一个临时对象吗?我没有看到这样做会有任何不安全的地方。而且由于大多数移动构造函数都非常快,所以为了进行小规模的过早优化来使代码变得复杂似乎没有必要。 - aschepler