2016-04-08 3 views
0

Странное поведение конструктора копирования для push_back, emplace и insert.push_back vs emplace vs insert in vector in C++

#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 называет его трижды. Я не могу понять, в чем причина этого.

+0

Перераспределение предыдущих элементов. – LogicStuff

+0

Вам действительно нужна эта стена кода, чтобы узнать, как часто вызывается конструктор копирования? Пожалуйста, сделайте это более минимальным. И кстати, вы забыли задать вопрос;) – user463035818

+0

Вопрос: почему конструктор копирования вызывался более одного раза в случае вставки и emplace, а во-вторых, когда я использовал вставку или emplace для вставки первого элемента вместо того, чтобы нажимать назад, конструктор копирования был (tobi303) Извините за огромный код. Пожалуйста, исключите ненужную часть. (LogicStuff) Извините, я не получаю ваш ответ, пожалуйста, подробно расскажите подробнее. – user3798283

ответ

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.

+0

Пожалуйста, ** не просто ** зарезервируйте 99999 элементов для простой тестовой программы. Добавьте еще несколько номеров, и появится новая проблема. Резервирование разумной суммы в порядке, но резервирование 99999 элементов для, представьте, привет, мировая программа будет слишком много, нет? – aslg

+0

уверен, конечно. Это не настоящий код мира. В любом случае, вы правы, я собираюсь отредактировать. благодаря –