为什么在这里调用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"); }
中间的数字来自哪里?为什么可以是3或2?适用于为什么在这里调用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”通过转换构造
g
中的return
语句,也可能适用于其他地方。引自参考文献:
复制省略是唯一允许改变的优化形式
可观察到的副作用。因为有些编译器不执行
在允许复制省略的任何情况下(例如,在调试中
模式),依赖复制/移动的副作用的程序
构造函数和析构函数是不可移植的
因此,对于您的示例代码,输出无法在不同的实现中可靠地预测。理论上,这可以打印
131
、13313
、1313
和1331
中的任何一种。这是一个相当愚蠢的测验问题
f(“你好”)代码>:
- “hello”通过转换构造函数转换为临时的
,打印X
1
- 临时
用于初始化函数参数,调用移动构造函数,打印X
。这可以省略3
用于初始化临时返回值,调用移动构造函数,打印x
。它是一个函数参数,因此不允许省略,但返回是一个隐式移动3
- “hello”通过转换构造函数转换为临时的
g(“你好”)代码>
- “hello”用于通过转换构造函数构造
,打印c
1
用于初始化临时返回值,调用移动构造函数,打印c
。这可以省略3
- “hello”用于通过转换构造函数构造
至于打印
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