2015-08-27 2 views
6
#include <iostream> 
#include <vector> 

class A 
{ 
public: 
    A() { std::cout << "constructor" << std::endl; } 

    ~A() { std::cout << "destructor" << std::endl; } 
}; 

int main() 
{ 
    std::vector<A> myvec; 
    myvec.push_back(A()); 
    myvec.push_back(A()); 
    myvec.clear(); 
    return 0; 
} 

выход:Путаница после станд :: вектор строительства/разрушения в векторе :: ясном

constructor 
destructor 
constructor 
destructor 
destructor 
destructor 
destructor 

Есть пять вызовов деструктора здесь. Первые два связаны с временными, которые передаются push_back. Есть еще три вызова, но я ожидал еще два дополнительных звонка.

myvec.clear() очистит только два содержимого, поэтому деструктор A должен вызывать только два раза (вместо трех). почему существует один дополнительный деструктор времени?

Но, если я нажимаю только один элемент на вектор, а не на два, вывод будет таким, каким я ожидал.

+0

А как насчет деструкторов, называемых временными объектами, которые копируются? –

+4

Перераспределение происходит, когда емкость должна увеличиваться с 1 до 2. –

+0

добавить int в A(), использовать разные значения в конструкторах и показать его в конструкторе/деструкторе, только для отладки – Pieter21

ответ

8

Вызов std::vector::clear не очень важно в этом контексте, потому что, когда myvec выходит из области видимости, его содержимое будет уничтожено в любом случае.


Рассмотрим

class A 
{ 
public: 
    A() { std::cout << "constructor" << std::endl; } 
    ~A() { std::cout << "destructor" << std::endl; } 
    A (const A &) { std::cout << "A(A&)\n"; } 

}; 

int main() 
{ 
    std::vector<A> myvec; 

    std::cout << "First\n"; 
    myvec.push_back(A()); 

    std::cout << "Second\n"; 
    myvec.push_back(A()); 

    std::cout << '\n'; // to separate the final destruction 

    myvec.clear(); 
} 

, который выводит

First 
constructor <-- First A _temporary_ object created when pushing_back 
A(A&)  <-- vector makes a *copy* of the temporary 
destructor <-- Temporary A is destroyed 
Second  
constructor <-- Second A _temporary_ object created when pushing_back 
A(A&)  <-- Reallocation happens: vector can't copy because it ran out of space 
A(A&)  <-- Copy of the second temporary 
destructor <-- Destroy of the temporary 
destructor <-- Destroy of the first element 

destructor 
destructor 

Если вы std::vector::reserve некоторое пространство, вы можете избавиться от копий, сделанных перераспределении

std::vector<A> myvec; 
myvec.reserve(8); 

который конф ИСУР что сказал

First 
constructor 
A(A&) 
destructor 
Second 
constructor 
A(A&) 
destructor 

push_back все еще делает копию параметра: это может быть дополнительно оптимизировано путем создания вашего класса подвижен.

A(A&&) noexcept = default; 
A& operator=(A&&) noexcept = default; 

First 
constructor 
destructor 
Second 
constructor 
destructor 
+0

Thnks много для ур подробное объяснение @black. , –

+0

Перенос семантики и '= default' доступны только для C++ 11. – edmz

5

Это, скорее всего, связано с перераспределением, которое происходит между первым и вторым push_back. Если вы reserve некоторое пространство раньше времени, то the deallocations are going to be 2 после двух push_back s, как вы и ожидали.

5

Попробуйте немного изменить версию своей программы. Теперь есть конструктор копирования и необязательный reserve (см. Комментарий в программе). Будет намного яснее, что происходит.

#include <iostream> 
#include <vector> 

using namespace std; 


class A 
{ 
    public: 
    A()   { cout << " constructor" << endl; } 
    A(const A & a) { cout << " copy constructor" << endl; } 
    ~A()   { cout << " destructor" << endl; } 
}; 



int main() 
{ 
    vector<A> myvec; 

    // myvec.reserve(100);     // <<< remove comment to see the difference 

    cout << "pushback 1" << endl; 
    myvec.push_back(A()); 

    cout << "pushback 2" << endl; 
    myvec.push_back(A()); 

    cout << "pushback 3" << endl; 
    myvec.push_back(A()); 

    cout << "clear" << endl; 
    myvec.clear(); 
    cout << "end clear" << endl; 
    return 0; 
} 
+0

Это недопустимо C++, потому что ваш конструктор копий принимает неконстантную ссылку, но вызовы 'push_back' должны копировать временные, которые не могут связываться с неконстантной ссылкой. Он компилируется с VC++, потому что причины. –

+0

@JonathanВлажно правильно, только что отредактировал код. –

Смежные вопросы