push_back vs emplace vs在C ++中的向量中插入

时间:2016-04-08 11:28:17

标签: c++ copy-constructor

push_backemplaceinsert的复制构造函数的奇怪行为。

#include<iostream>
#include<memory>
#include<vector>
using namespace std;
class Test
{
   private:
   int *big;
   public:
   void make_null() 
   { 
      delete [] big;
      big = NULL;
      cout<<"Made NULL\n";
   }
   void show() { cout<<"Memory Allocated\n"; }
   Test ()
   {
      big = new int[10000];
      cout<<"Default Constructor gets called \n";
   }
   Test( const Test &a)
   {
      big = new int[10000];
      int k;
      for(k = 0; k < 10000 ; k++)
         big[k] = a.big[k];  
      cout<<"Copy Constructor gets called \n";
   }
   Test & operator = ( const Test &a)
   {
      if(this != &a)
      {
         delete [] big;
         if(a.big)
         {
           big = new int[10000];
           int k;
           for(k = 0; k < 10000 ; k++)
              big[k] = a.big[k];  
           cout<<"New memory gets allocated \n";
         }
         else
         {
           big = NULL;
           cout<<"NULL value gets assigned \n";
         }
      }
      else
         cout<<"Same pointer assignment\n";      
      cout<<"Assignment operator gets called \n";
        return *this;
   }
    ~Test ()
   {
      delete [] big;
      cout<<"Destructor gets called \n";
   }
};
int main()
{
   Test tObj;
   vector<Test> tVec;
   tVec.push_back(tObj);
   tVec[0].show();
   cout<<"++++++++++++++++++++++++++++++++++++++++++++++++++\n";
   Test rObj;
   tVec.emplace(tVec.end(),rObj);
   tVec[1].show();
   cout<<"++++++++++++++++++++++++++++++++++++++++++++++++++\n";
   Test qObj;
   tVec.insert(tVec.end(),qObj);
   tVec[2].show();
   cout<<"++++++++++++++++++++++++++++++++++++++++++++++++++\n";
   Test sObj;
   vector<Test> sVec;
   sVec.push_back(sObj);
   sVec[0].show();
   cout<<"++++++++++++++++++++++++++++++++++++++++++++++++++\n";
   tVec[0] = tVec[0];
   tVec[0] = sVec[0];
   sVec[0].make_null();
   tVec[1] = sVec[0];
   return 0;
}

输出:

Default Constructor gets called 
Copy Constructor gets called 
Memory Allocated
++++++++++++++++++++++++++++++++++++++++++++++++++
Default Constructor gets called 
Copy Constructor gets called 
Copy Constructor gets called 
Destructor gets called 
Memory Allocated
++++++++++++++++++++++++++++++++++++++++++++++++++
Default Constructor gets called 
Copy Constructor gets called 
Copy Constructor gets called 
Copy Constructor gets called 
Destructor gets called 
Destructor gets called 
Memory Allocated
++++++++++++++++++++++++++++++++++++++++++++++++++
Default Constructor gets called 
Copy Constructor gets called 
Memory Allocated
++++++++++++++++++++++++++++++++++++++++++++++++++
Same pointer assignment
Assignment operator gets called 
New memory gets allocated 
Assignment operator gets called 
Made NULL
NULL value gets assigned 
Assignment operator gets called 
Destructor gets called 
Destructor gets called 
Destructor gets called 
Destructor gets called 
Destructor gets called 
Destructor gets called 
Destructor gets called 
Destructor gets called 

push_back调用复制构造函数一次,而emplace调用它两次, 并insert称之为三次。 我无法弄清楚背后的原因是什么。

1 个答案:

答案 0 :(得分:0)

在主要功能中以及此行之后:

vector<Test> tVec;

只需添加:

tVec.reserve(N); // N is the number of items you think that you are going to add to the vector

你的问题会消失。

<强>为什么吗

std::vector添加元素(推送,插入或插入)时,可能会发生重新分配。重新分配将导致将所有项目复制到内存(堆)的新位置。复制元素将默认调用复制构造函数,然后调用析构函数以获取旧项目。

tVec.reserve(N);将保留连续的内存块。这将阻止重新分配(或更好地说,不需要),直到推送元素的计数小于N