C++ Vector и его метод Push_back

152
25 сентября 2018, 12:20

Имеется некий код:

A a1;
A a2;
A a3;
std::vector<A> a;
std::cout << "Push back a1" << std::endl;
a.push_back(a1);
std::cout << "Push back a2" << std::endl;
a.push_back(a2);
std::cout << "Push back a3" << std::endl;
a.push_back(a3);

И разумеется класс А.

class A {
static int ACount;
private:
public:
A() {
    std::cout << "Constructor called. Objects = " << ++ACount << std::endl;
}
~A() {
    std::cout << "Destructor called. Objects = " << --ACount << std::endl;
}
A(const A &a) {
    std::cout << "Copy Constructor called. Objects = " << ++ACount << 
std::endl;
}
};
int A::ACount;

Вывод с консоли такой:

Constructor called. Objects = 1
Constructor called. Objects = 2
Constructor called. Objects = 3
Push back a1;
Copy constructor called. Objects = 4
Push back a2;
Copy constructor called. Objects = 5
Copy constructor called. Objects = 6
Destructor called. Objects = 5
Push back a3;
Copy constructor called. Objects = 6
Copy constructor called. Objects = 7
Copy constructor called. Objects = 8
Destructor called. Objects = 7
Destructor called. Objects = 6
Destructor called. Objects = 5
Destructor called. Objects = 4
Destructor called. Objects = 3
Destructor called. Objects = 2
Destructor called. Objects = 1
Destructor called. Objects = 0

Не могу понять почему при вызове метода Push_back(а2) вызывается 2 раза конструктор копирования, а при Push_back(а3) целых 3 раза. Пытаюсь создать некое подобие граф движка и создание\уничтожение такого числа объектов мне очень навредит. Как быть? Или стоит поискать некий иной контейнер?

Answer 1

Происходит переаллокация вектора при каждом push_back. Вы видите вызовы конструкторов копирования для копирования элементов со старого места на новое, а затем деструкцию элементов на старом месте.

Сделайте предварительное

a.reserve(100);

и "лишние" копирования и деструкции пропадут.

Answer 2

Не могу понять почему при вызове метода Push_back(а2) вызывается 2 раза конструктор копирования, а при Push_back(а3) целых 3 раза

При увеличении размера вектора создается новый вектор, в него копируются все элементы старого и заpushенный элемент, а затем все элементы старого уничтожаются.

Это связанно с тем, что вектор гарантирует последовательное непрерывное хранение элементов в памяти.

Как быть?

Можно заранее зарезервировать достаточное количество элементов.

Или стоит поискать некий иной контейнер?

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

У вектора поиск произвольного элемента идет за константное время, а добавление нового (если специально не резервировать пространство) - за O(N). Также вектор можно передавать в функции как указатель на C-like массив.

У списка за константное время идет поиск, добавление и удаление первого и последнего элемента, а произвольного элемента - за O(N).

READ ALSO
Можно ли перегрузить опреатор [] как не член класса?

Можно ли перегрузить опреатор [] как не член класса?

В целом вопрос в заголовке, не знаю что ещё добавить, кроме примера

154
Code::Blocks и CMake - запускаемый проект по умолчанию

Code::Blocks и CMake - запускаемый проект по умолчанию

Продолжая знакомиться с Code::Blocks возник вопрос по связке его с CMakeКак в CMake назначить запускаемый проект по умолчанию ?

153
C++ передача указателя в функцию

C++ передача указателя в функцию

Есть функция с сигнатурой:

195
c++: std::in, _getch() работаю некорректно

c++: std::in, _getch() работаю некорректно

Для отладки программы необходимо приостанавливать работу программы, порционно выводить некоторую информацию на экран и затем по команде...

178