为什么在这里调用move构造函数? 这是一个C++测试的代码示例: #include <iostream> struct X { X(const char *) { std::cout << 1; } X(const X &) { std::cout << 2; } X(X &&) { std::cout << 3; } }; X f(X a) { return a; } X g(const char * b) { X c(b); return c; } int main() { f("hello"); g("hello"); }

为什么在这里调用move构造函数? 这是一个C++测试的代码示例: #include <iostream> struct X { X(const char *) { std::cout << 1; } X(const X &) { std::cout << 2; } X(X &&) { std::cout << 3; } }; X f(X a) { return a; } X g(const char * b) { X c(b); return c; } int main() { f("hello"); g("hello"); },c++,c++11,move-semantics,C++,C++11,Move Semantics,中间的数字来自哪里?为什么可以是3或2?适用于g中的return语句,也可能适用于其他地方。引自参考文献: 复制省略是唯一允许改变的优化形式 可观察到的副作用。因为有些编译器不执行 在允许复制省略的任何情况下(例如,在调试中 模式),依赖复制/移动的副作用的程序 构造函数和析构函数是不可移植的 因此,对于您的示例代码,输出无法在不同的实现中可靠地预测。理论上,这可以打印131、13313、1313和1331中的任何一种。这是一个相当愚蠢的测验问题 f(“你好”): “hello”通过转换构造

中间的数字来自哪里?为什么可以是3或2?

适用于
g
中的
return
语句,也可能适用于其他地方。引自参考文献:

复制省略是唯一允许改变的优化形式 可观察到的副作用。因为有些编译器不执行 在允许复制省略的任何情况下(例如,在调试中 模式),依赖复制/移动的副作用的程序 构造函数和析构函数是不可移植的


因此,对于您的示例代码,输出无法在不同的实现中可靠地预测。

理论上,这可以打印
131
13313
1313
1331
中的任何一种。这是一个相当愚蠢的测验问题

  • f(“你好”)

    • “hello”通过转换构造函数转换为临时的
      X
      ,打印
      1
    • 临时
      X
      用于初始化函数参数,调用移动构造函数,打印
      3
      。这可以省略
    • x
      用于初始化临时返回值,调用移动构造函数,打印
      3
      。它是一个函数参数,因此不允许省略,但返回是一个隐式移动
  • g(“你好”)

    • “hello”用于通过转换构造函数构造
      c
      ,打印
      1
    • c
      用于初始化临时返回值,调用移动构造函数,打印
      3
      。这可以省略
记住,函数总是必须构造它们返回的东西,即使调用代码刚刚丢弃了它


至于打印
2
,这是因为您使用的古老编译器没有实现隐式-move-when-returning-a-local-variable规则。

复制省略()不是强制性的。您不能依赖此优化。所以返回语句输出的结果没有什么不可靠的。这是谁写的“测验”?这个程序可以有效地打印四个不同的输出。@ T.C在ACCU 2014年中被称为C++ PUB测验,不要忘记GCC 4.4是一个2009编译器,所以隐式的返回还没有。GCC 4.4甚至如何接受<代码> -STD= C++ 11 < /代码>?它唯一知道的是
-std=c++0x
。复制省略不适用于
f
@T.c.Oops中的返回。它是参数。是否有理由必须使用(可能省略)临时变量来初始化
f
的参数?为什么不能直接从参数初始化参数?@Angew参数传递的是复制初始化。(在这里插入[dcl.init]/17.6.2的冗长引用)谢谢,[dcl.init]/15是我错过的。如果编译器执行NRVO,也可能是结果。还是我错了?@Bццћ不,你不能用函数参数进行NRVO。
g++ -std=c++11 -Wall -Wextra -O -pthread