当前位置: 首页 > 工具软件 > Elide > 使用案例 >

gcc参数 -fno-elide-constructors怎么回事儿?

陆宏壮
2023-12-01

好奇怪!复制构造函数居然不被调用了?

我在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(),函数中会调用复制构造,细节如下:

  1. 函数内部创建d 会调用赋值构造 生成一个临时变量给d,临时变量立刻析构
  2. 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++强制在所有情况下调用复制构造函数。

参考资料

1
2

 类似资料: