c++ - 返回类型和 move 语义

标签 c++ c++11 move-semantics

<分区>

#include <iostream>
struct X
{
     X(const char *) { std::cout  << 1; }
     X(const X&) {std::cout << 2;} //copy ctor;
     X(X&& ) {std::cout << 3;} //Move ctor;
};

X f(X a)
{
    return a; //a will be moved out of f calling X's move ctor
}

X g(const char* b)
{
    X c(b); 
    return c;
}
int main()
{
   f("hello");
   g("hello");

   //prints 131 and not 1313
}

为什么上面程序的输出是131?按照我的理解应该是1313

即当 f 返回时在同一行上调用 move 构造函数时,当 g 返回时也应调用 move 构造函数。

最佳答案

欢迎来到 ACCU 2014! :-)

f 中,一个人得到 a 的隐式 move ,因为您返回的是按值函数参数。

g 中,一个人得到了 c 的隐式 move ,因为你正在返回一个本地自动存储变量。

只有这些信息,那么你的理解是正确的:1313。如果编译器输出这个,它就是符合的。

额外的信息来自 [class.copy]/p31,它描述了何时允许“返回值优化”(RVO)。 f 中不允许使用 RVO,但 g 中允许使用 RVO。我确实没有充分的理由知道 f 中不允许使用 RVO,除了我所知道的编译器都没有想出如何实现它这一事实。因此,没有动力更改规范以允许它。

我所知道的所有编译器都为 g 实现了 RVO,因此最终的 move 构造被优化掉了——尽管它有副作用。所以 RVO 不是“纯粹的优化”。正因为如此,为了实现它,标准必须对这种(可观察的)“优化”给予特别许可。

关于c++ - 返回类型和 move 语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23006717/

相关文章:

C++ 将指针转换为对函数参数中基类指针的引用

c++ - 将 vector 的元素求和分配给另一个 vector 的元素的并行算法

c++ - 为什么我的交换方法会干扰 make_move_iterator?

move-semantics - cppcheck 知道 move 语义吗?

data-structures - 用另一种数据结构在Rust中初始化数据结构的字段

c++ - 除了 boost 之外,在 C++ 中获取目录中所有文件的跨平台方式

c++ - std::basic_string 是否正式具有隐式生成的 move 构造函数?

C++ 使用以 vector 作为值的 map

c++ - 将 lambda 传递给对象并从 lambda 内部修改该对象

c++ - 在方法名之前或之后放置 const、static 和 virtual?