C++ vector push_back 方法和临时对象创建

标签 c++ c++11 vector copy-constructor push-back

下面是 C++ 中 vector 推回方法的签名。

 void push_back (const value_type& val);

下面是代码

class MyInt
{
   int *a;
public:
  MyInt(int n):a(new int(n)){cout<<"constructor called"<<endl;}
   ~MyInt(){cout<<"destructor called"<<endl;}
   void show(){
   cout<<*a<<endl;
   }
 };


 void vector_test(vector<MyInt> &v)
 {
    MyInt m1(1);
    MyInt m2(2);
    v.push_back(m1);   
    v.push_back(m2);
 }



Output
-------------
constructor called
constructor called
destructor called
destructor called
destructor called
1
2
destructor called
destructor called

这里我们看到在 vector_test 函数中创建的 2 个对象导致 2 次 构造函数调用。 但对于析构函数,它被调用了 5 次。

现在我的疑惑和问题是

  1. 为什么构造函数和析构函数的调用次数不匹配?
  2. 我了解到正在创建一些临时对象。但这种机制是如何运作的?
  3. 只是为了测试,我尝试提供一个复制构造函数,但它会导致编译失败。可能是什么原因?
  4. 是否有一些逻辑将 m1 和 m2 的内容复制到新对象中并放入容器中?

如果有人能详细解释一下,我将不胜感激。谢谢..

最佳答案

您还需要为复制构造函数添加日志记录:

MyInt(const MyInt& rhs):a(new int(*rhs.a)){cout<<"copy constructor called"<<endl;}

编译器允许省略某些构造函数调用,即。在以下行中:

MyInt m1 = 1;

您可能希望首先调用复制构造函数来实例化临时 MyInt(1)然后用这个临时调用一个复制构造函数。所以你会看到:

constructor called // for temporary
copy constructor called // for m1
destructor called       // for m1
destructor called  // for temporary

但由于复制省略编译器将直接实例化您的 m1使用 MyInt(int n) 的实例构造函数,即使您的复制构造函数有副作用(使用 std::cout)。所以没有以上 // for temporary日志将存在。

要使用 gcc 查看此信息,请使用:-fno-elide-constructors禁用复制构造函数省略的选项。

此外,构造函数也是一个好习惯,例如 MyInt(int n)明确的,这是不允许制作MyInt错误的对象实例 - 你必须将其明确化,即 MyInt var; var = static_cast<MyInt>(1); .

关于C++ vector push_back 方法和临时对象创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37078038/

相关文章:

C++ 动态(多阶段)3D vector 实例化和元素分配

c++ - 指向成员的成员的指针

c++ - C++ 中的错误分配异常

c++ - 是否可以将别名模板标记为好友?

c++ - 链接隐式转换运算符

r - 如何交换 R 中两列中的值?

c++ - 调用 vkEnumerateDeviceExtensionProperties "twice"- 是否需要?

c++ - DirectX 12 资源绑定(bind)

c++ - (bool) cast 的默认行为

c++ - vector push_back() 给出编译器错误 C2280