Странное поведение при изменении размера контейнера

при изменении размера вектора он вызовет конструктор, а затем уничтожит его.

struct CAT
{
    CAT(){cout<<"CAT()"<<endl;}
    CAT(const CAT& c){cout<<"CAT(const CAT& c)"<<endl;};
    ~CAT(){cout<<"~CAT()"<<endl;};
};
int main()
{
    vector<CAT> vc(6);
    cout<<"-----------------"<<endl;
    vc.resize(3);
    cout<<"-----------------"<<endl;

}

выход:

$./m 
CAT()
CAT(const CAT& c)
CAT(const CAT& c)
CAT(const CAT& c)
CAT(const CAT& c)
CAT(const CAT& c)
CAT(const CAT& c)
~CAT()
-----------------
CAT()          //why resize will call constructor?
~CAT()
~CAT()
~CAT()
~CAT()
-----------------
~CAT()
~CAT()
~CAT()

Я использую ubuntu 13.10 и gcc4.8

Ответ 1

Это из-за необязательного аргумента для resize.

Это реализация, которую я использую в GCC 4.8:

  void
  resize(size_type __new_size, value_type __x = value_type())
  {
if (__new_size > size())
  insert(end(), __new_size - size(), __x);
else if (__new_size < size())
  _M_erase_at_end(this->_M_impl._M_start + __new_size);
  }

Присмотритесь к value_type __x = value_type().

Из http://www.cplusplus.com/reference/vector/vector/resize/:

void resize (size_type n, value_type val = value_type());

Ответ 2

До С++ 11 resize имел второй аргумент по умолчанию, чтобы предоставить значение для инициализации новых элементов:

void resize(size_type sz, T c = T());

который объясняет, почему вы видите дополнительный объект, созданный и уничтоженный.

В современной библиотеке это заменяется двумя перегрузками

void resize(size_type sz);
void resize(size_type sz, const T& c);

поэтому вы не должны видеть никаких дополнительных объектов, если вы явно не предоставите их. Во время построения вы также должны увидеть инициализацию по умолчанию, а не копию-инициализацию.

Ответ 3

Возможно, что ваша реализация vector::resize создает временный объект с инициализацией по умолчанию даже при сокращении, потому что он использует его для инициализации новых элементов при его повышении.