Почему конструктор перемещения вызывается только тогда, когда в векторе уже есть элемент?

Я пытаюсь изучить новые функции в C ++ 11. И я тестирую следующий код в XCode.

#include <iostream>
#include <string>
#include <vector>

class CClass
{
std::string s;
public:
CClass()
{
std::cout<<"Default Constructor"<<std::endl;
}
CClass(const std::string v) :s(v) {
std::cout<<"Constructor"<<std::endl;
}

CClass(const CClass& other): s(other.s) {
std::cout<<"Copy Constructor"<<std::endl;
}
CClass(CClass&& a) noexcept
{
std::cout<<"Move Constructor"<<std::endl;
s = std::move(a.s);
}
CClass& operator = (const CClass& other)noexcept
{
std::cout<<"Copy Assignment"<<std::endl;
if(this != &other)
{
s = other.s;
}
return *this;
}
CClass& operator = (CClass&& other) noexcept
{
std::cout<<"Move Assignment"<<std::endl;
if(this != &other)
{
s = std::move(other.s);
}
return *this;
}
};

int main()
{
std::vector<CClass> v;
CClass x("hello");
//v.push_back(x);
std::cout<<"--------------------"<<std::endl;
v.emplace_back("uiuiu");
std::cout<<"--------------------"<<std::endl;
}

Когда я раскомментирую толчок назад, я получаю следующий результат:

Constructor
Copy Constructor
--------------------
Constructor
Move Constructor
--------------------

В противном случае, если я это прокомментирую, я получу:

Constructor
--------------------
Constructor
--------------------

Мой вопрос: почему конструктор перемещения не вызывается во втором случае? Он вызывается только в первом случае, когда вектор изначально не пуст.

3

Решение

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

От std::vector::emplace_back:

Если новый size() больше, чем capacity() тогда все итераторы и ссылки (включая итератор конца-в-конце) становятся недействительными. В противном случае только последний итератор становится недействительным.

Итераторы и ссылки становятся недействительными по той же причине: потому что элементы теперь хранятся в новом месте в памяти.

Если вы позвоните reserve в первом случае вы увидите, что конструктор перемещения не вызывается:

CClass x{"hello"}; // constructor
v.reserve(2); // make space for 2 elements (you could have also used resize)
v.push_back(x); // copy constructor
v.emplace_back("uiuiu"); // constructor
7

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector