以下是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");
}
该计划的输出是什么?
我想是这样的:
f(X a)
被调用,构造函数隐式将const char*
转换为X,因此输出为1 g(const char*)
被调用,X c(b)
X(const char*)
输出为1 所以答案是11.给测验的答案是131.我用g ++ 4.4.4-13得到的答案是121。
据说这段代码是用这个命令编译的:
g++ -std=c++11 -Wall -Wextra -O -pthread
中间数字来自哪里?为什么它可以是3或2?
答案 0 :(得分:17)
理论上,这可以打印131
,13313
,1313
和1331
中的任何一个。作为测验问题,它非常愚蠢。
f("hello");
:
X
,打印1
。X
用于初始化函数参数,调用移动构造函数,打印3
。这可以省略。x
用于初始化临时返回值,调用移动构造函数,打印3
。它是一个函数参数,因此不允许使用省略,但返回是隐式移动。 g("hello");
c
,打印1
。c
用于初始化临时返回值,调用移动构造函数,打印3
。这可以省略。请记住,函数总是必须构造它们返回的东西,即使它只是被调用代码丢弃了。
关于打印2
,因为你使用的古老编译器并没有实现隐式移动时返回本地变量规则。
答案 1 :(得分:3)
Copy elision适用于return
中的g
语句,也可能适用于其他地方。引自cppreference:
复制省略是唯一可以改变的优化形式 可观察到的副作用。因为有些编译器不能执行 在允许的每种情况下复制省略(例如,在调试中) 模式),依赖于复制/移动的副作用的程序 构造函数和析构函数不可移植。
因此,对于您的示例代码,无法在不同的实现中可靠地预测输出。