好奇怪!复制构造函数居然不被调用了?
我在Linux下写demo的时候遇到了一个非常奇怪的问题!代码如下,理论上是复制构造函数应该被调用的。但是结果没有!有时候预期的结果和你想的不一样可能是,被编译器优化了!
代码
class demo{
public:
demo(int a):m_i(new int(a)){
std::cout <<"demo()\n";
}
demo(const demo& ref):m_i(new int(*ref.m_i+1)){
std::cout<<"copy\n";
}
~demo(){
std::cout<<"~demo()\n";
}
public:
int *m_i;
};
demo getDemo(){
demo d = demo(1);
return d;
}
int main(){
demo obj = getDemo();
//demo a = obj;
std::cout<<*obj.m_i<<" obj m_i\n";
return 0;
}
代码分析
demo class,成员包括:构造函数、复制构造、析构函数,指针类型成员变量。想要初始化demo class就要开辟内存。复制构造函数不同的是,为所指向的int类型变量+1。
getDemo(),函数中会调用复制构造,细节如下:
- 函数内部创建d 会调用赋值构造 生成一个临时变量给d,临时变量立刻析构
- return demo 此处会调用复制构造,生成一个d的临时变量给return value, 然后d会立刻析构。
main(),会调用复制构造,分析如下:
demo obj = getDemo(); 调用复制构造,return value临时变量赋值给obj,然后临时变量立刻析构。
你认为的输出
demo()
copy
~demo()
copy
~demo()
copy
~demo()
4 obj m_i
~demo()
实际上经过g++ -g lionel.cpp -o lionel
只有,按理来说应该是4怎么还会是1呢,难道说没有经过复制构造函数?
demo()
1 obj m_i
~demo()
到底是怎么回事?
如果这样编译g++ -g lionel.cpp -o lionel -fno-elide-constructors
就会出现我们期望的输出:
demo()
copy
~demo()
copy
~demo()
copy
~demo()
4 obj m_i
~demo()
输出可见m_i为4 说明调用的3次复制构造。那么-fno-elide-constructors是什么呢?
-fno-elide-constructors的深入理解
-fno-elide-constructors
The C++ standard allows an implementation to omit creating a temporary
that is only used to initialize another object of the same type.
Specifying this option disables that optimization, and forces G++ to
call the copy constructor in all cases.
标准c++允许一种实现:去省略创建用来初始化另一个相同类型的对象的临时变量(触发复制构造函数)(就是在触发复制构造函数的时候避免产生临时变量
)编译之后不产生临时变量,用来提升性能。当你把选项开启时,G++强制在所有情况下调用复制构造函数。