Понимание конструкции, копирования и уничтожения при вставке объектов в вектор - PullRequest
0 голосов
/ 11 сентября 2018

Я пытаюсь понять, как STL обрабатывает вставки объектов.Я понимаю, что STL вызывает конструктор или копию конструкции из временного.

Это код, который я пытаюсь понять:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class A
{
      public:
      int ObjId;;
      A(int id) : ObjId(id)
      {
            cout << "Constructing object with id: " << ObjId << endl;
      }

      A(const A& objToCpy)
      {
            ObjId = objToCpy.ObjId;
            cout << "Copying object with id: " << ObjId << endl;
       }

      ~A()
      {
            cout << "Destructing object with id: " << ObjId << endl;
      }
};


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

      vecOfA.push_back(A(1));

      cout << "....................." << endl << endl;

      vecOfA.push_back(A(2));

      return 0;
}

Это дает следующий вывод:

Построение объекта с идентификатором: 1

Копирование объекта с идентификатором: 1

Уничтожение объекта с идентификатором: 1

................

Построение объекта с идентификатором: 2

Копирование объекта с идентификатором: 2

Копирование объекта с идентификатором: 1

Уничтожение объекта с идентификатором: 1

Уничтожение объекта с идентификатором: 2

................

Уничтожение объекта с помощьюid: 1

Уничтожение объекта с id: 2

Я могу понять первую вставку.Создается временный объект с ID = 1, который затем копируется, создается и вставляется в вектор.И этот временный затем разрушается.

Однако я не понимаю, почему скопированный объект имеет ID = 0, а не 1.

Что касается второй части, я понятия не имею, что происходит и почему это не так.идентичен первой вставке, за исключением того, что идентификатор отличается.Почему создаются 2 копии объекта, и оба с ID = 0, а не 2.

Кто-нибудь может мне помочь понять это поведение?

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

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

Набрав A(const A& other) {...} вы определяете свой собственный конструктор копирования, а это означает, что вы показываете, как копируется каждое поле, поэтому вы пропускаете оператор ObjId = other.ObjId в своем конструкторе.

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

0 голосов
/ 11 сентября 2018

Однако я не понимаю, почему скопированный объект имеет ID = 0, а не 1.

Ваш конструктор копирования оставляет ObjId неинициализированным, поэтому поведение программы не определяется при доступе к значению.


Что касается второй части, я понятия не имею, что происходит и почему она не идентична первой вставке, за исключением того, что идентификатор отличается. Почему построено 2 объекта копирования

Это связано с тем, как работает структура данных динамического массива - то, чем является std::vector. Массивы не могут быть изменены. Если внутренний массив вектора слишком мал, создается больший массив, старые элементы копируются (или перемещаются) в новый массив, а старый массив уничтожается.


Это означает, что вектор обычно инициализируется до 1?

Один эксперимент не говорит, что делает вектор , обычно . Похоже, что после первого нажатия, емкость действительно была в этом случае в вашей системе. Нет гарантии, что это будет один в других случаях (например, другая реализация std::vector).

...