在C ++中考虑以下代码:
struct A {A(int);};
A foo() {return static_cast<A>(0);}
A x = foo();
这里static_cast<A>(0)
通过标准[5.2.9-4]创建一个临时对象,它是一个prvalue。标准[12.2-1]说
类型的临时数在各种上下文中创建:绑定对prvalue的引用(8.5.3),返回prvalue (6.6.3),这是一个创建prvalue的转换(4.1, 5.2.9,5.2.11,5.4),抛出异常(15.1),进入处理程序(15.3),并进行一些初始化(8.5)。
那么return语句会再次创建一个临时对象吗?
顺便问一下,任何人都可以告诉我标准是否保证隐式类型转换会创建一个临时对象吗?
答案 0 :(得分:7)
(§4/ 6)提到
任何隐式转换的效果与执行相应的声明和初始化相同,然后使用临时变量作为转换的结果。
所以是的,除非经过优化,否则应该创建一个临时的,但我确信所有现代编译器都会在您的情况下执行复制省略。此特定优化称为return value optimization (RVO)。您可以通过具有副作用的构造函数来轻松地测试它:
struct A {
A(int){
std::cout << "ctor";
}
A(const A & other)
{
std::cout << "copy ctor";
}
A(A&&other)
{
std::cout << "move ctor";
}
};
答案 1 :(得分:5)
临时对象(最有可能)将通过Return-Value-Optimization(RVO)进行优化。
示例:
#include <iostream>
struct A
{
A(int)
{
std::cout<< "A" << std::endl;
}
A(const A&)
{
std::cout << "A&" << std::endl;
}
A(A&&)
{
std::cout << "A&&" << std::endl;
}
};
A foo() {return static_cast<A>(0);}
int main()
{
A x = foo();
return 0;
}
输出:live example
A
禁用RVO的输出:live example
A
A&&
A&&
答案 2 :(得分:4)
简短回答:不会在代码中只创建一个A
。
为实现此目的,编译器使用(Named) Return value optimization来消除返回时不必要的对象创建/复制。更一般的情况Copy elision,消除了不必要的对象复制,将在大量相关案例中使用。
您可以使用GCC
选项-fno-elide-constructors
来查看差异。
答案 3 :(得分:2)
此特定情况下的实际结果取决于特定的编译器和优化级别。实际上,具有良好优化级别的现代编译器可以完全删除任何临时对象。考虑一下:
extends
gcc-5.1.1 with -O4构建一个可执行文件,输出字面意思:
#include <iostream>
using namespace std;
struct A {
A(int) { cout << __PRETTY_FUNCTION__ << endl; }
~A() { cout << __PRETTY_FUNCTION__ << endl; }
};
inline
A foo() {
return static_cast<A>(0);
};
int main(void) {
A a = foo();
cout << "hello world!" << endl;
}