【问题标题】:copy constructor,destructor and temporaries复制构造函数、析构函数和临时对象
【发布时间】:2015-12-05 11:55:18
【问题描述】:

我写了这个类来测试默认构造函数、复制构造函数、赋值运算符和析构函数的行为:

#include <iostream>

class Test {

  public:
    Test();

    Test(const Test&);

    ~Test();

    Test &operator=(const Test&);

  private:
    static int count;
    int label;

};

Test::Test() : label(count++) 
{
  std::cout<<"constructor of "<<label<<std::endl;
}

Test::Test(const Test &other) : label(count++)
{
  std::cout<<"copy-constructor of "<<label<<std::endl;
}

Test::~Test()
{
  std::cout<<"destructor of "<<label<<std::endl;
}

Test &Test::operator=(const Test &other)
{
  std::cout<<"copy assignment operator of "<<label<<std::endl;
}

int Test::count=0;

我在不同的上下文中使用这个类来深入理解每个函数的调用方式和时间:我期望 cmets 中的行为:

#include "Test.h"



// argument passed and returned by reference 
const Test &funct_by_ref(const Test &ref)
{
  return ref;
}

// argument passed and returned by value
// call copy constructor to initialize parameter
Test funct_by_val(Test val)
{
  // calls copy constructor to initialize temporary
  return val;
}  // exits local scope,val is destroyed,calls val destructor 



int main()
{
  // creates a temporary,calls 0 default constructor 
  Test();  // the temporary is destroyed at the end of the expression that created it
           // calls 0 destructor
  // creates a temporary (calls 1 default constructor) and calls 2 copy constructor 
  Test t2=Test(); // same as Test t2((Test()));
  std::cout<<"--------------------------------"<<std::endl;
  // calls 3 copy constructor
  Test t3=t2;
  // calls 4 default constructor
  Test t4;
  {
    // calls 5 copy constructor
    Test t5(t4);
  } // local scope,t5 is destroyed,calls 5 destructor
  // calls 4 assignment operator 
  t4=t2;
  std::cout<<"-------------------------------"<<std::endl;
  // nothing happens here
  funct_by_ref(t4);
  std::cout<<"-------------------------------"<<std::endl;
  // calls copy constructor twice 6,7
  funct_by_val(t4);
  // temporary is destroyed at the end of the expression,calls destructor
}

但我得到以下输出:

constructor of 0
destructor of 0
constructor of 1
------------------------
copy-constructor of 2
constructor of 3
copy-constructor of 4
destructor of 4
copy assignment operator of 3
--------------------------
---------------------------
copy-constructor of 5
copy-constructor of 6
destructor of 6
destructor of 5
destructor of 3
destructor of 2
destructor of 1

一切都很好,直到第一个 ----------------- 它似乎跳过了对象的创建(我想到了初始化 t2 的临时 uset,因为它不是在那条线之后立即销毁),因此计数减一..

【问题讨论】:

  • 从 C++11 开始,还需要添加 Test(Test&amp;&amp;); 才能看到移动构造函数。
  • @Jarod42 是的,但现在让我们保持简单...
  • 更改变量名称的索引,您开始用 1 计算变量,用 0 计算内部值,这就是为什么“偏移量”为 1。
  • 你有复制省略号Test t2=Test();:相当于Test t2;
  • 您可以尝试使用-fno-elide-constructors 以获得您预期的结果。

标签: c++ destructor copy-constructor assignment-operator temporaries


【解决方案1】:
Test t2=Test(); // same as Test t2((Test()));

这里的编译器是(并且可以)eliding the copy 并且将具有与执行相同的效果:

Test t2;

【讨论】:

    【解决方案2】:

    如果检测临时对象存在的唯一方法是跟踪构造函数和析构函数调用,则该标准有特定条款允许 - 但不要求 - 实现省略(即省略创建)临时对象。

    您看到的差异是因为您预期的行为基于临时对象的创建和销毁,而编译器选择不创建这些临时对象。请注意,省略临时变量的决定因实现而异(并且通常受优化设置的影响)。

    【讨论】:

      猜你喜欢
      • 2010-12-22
      • 2016-10-10
      • 1970-01-01
      • 2011-01-20
      • 1970-01-01
      • 1970-01-01
      • 2010-10-08
      • 2013-10-13
      • 2015-12-14
      相关资源
      最近更新 更多