【发布时间】:2015-06-25 08:44:02
【问题描述】:
我正在观看 STL 的“Don’t Help the Compiler”演讲,他在幻灯片 26 上有一个类似的例子:
struct A
{
A() = default;
A(const A&) { std::cout << "copied" << std::endl; }
A(A&&) { std::cout << "moved" << std::endl; }
};
std::pair<A, A> get_pair()
{
std::pair<A, A> p;
return p;
}
std::tuple<A, A> get_tuple()
{
std::pair<A, A> p;
return p;
}
std::tuple<A, A> get_tuple_moved()
{
std::pair<A, A> p;
return std::move(p);
}
有了这个,下面的调用:
get_pair();
get_tuple();
get_tuple_moved();
产生这个输出:
moved
moved
copied
copied
moved
moved
get_pair 的结果是移动构造的,正如预期的那样。一个动作也可能被 NRVO 完全忽略,但它不在当前问题的主题范围内。
get_tuple_moved 的结果也是移动构造的,这是明确指定的。但是,get_tuple 的结果是复制构造的,这对我来说完全不明显。
我认为传递给return 语句的任何表达式都可能被认为具有隐含的move,因为编译器知道它无论如何都会超出范围。好像我错了。有人可以澄清一下,这里发生了什么吗?
另请参阅相关但不同的问题:When should std::move be used on a function return value?
【问题讨论】:
-
您是否禁用了复制省略?另外,最好发布一个真正的 MCVE。
-
@juanchopanza 其实是一个真正的MCVE,只是把调用方法放在
main()里。无论 RVO 如何,get_tuple和get_tuple_moved的行为都是相同的,而get_pair会受到影响。 -
@Mikhail:所以它实际上 不是 一个真正的 MCVE(因为它需要比复制和粘贴更多的工作,尽管只是其中的一小部分):-)
-
@DietmarKühl,好的,你说得对,我会解决的:)
标签: c++ c++11 c++14 move-semantics