#c #c 11 #constructor #move-semantics
#c #c 11 #конструктор #переместить-семантика
Вопрос:
Я просто читаю «Эффективный современный C » Скотта Мейерса и тестирую такой код:
class A
{
public:
A(int _a) : a(_a)
{
printf("Constructor A %dn",a);
}
A(Aamp;amp; tmp) noexcept
{
printf("MOVE constructorn");
a=std::move(tmp.a);
}
A(const A amp; tmp)
{
printf("COPY constructorn");
a= tmp.a;
}
private:
int a;
};
std::vector<A> v;
void fun(A temp)
{
v.push_back(std::move(temp));
}
void fun2(Aamp;amp; temp)
{
v.push_back(std::move(temp));
}
int main()
{
A x(3);
fun(x);
printf("n");
fun(A(5));
printf("n");
fun2(A(6));
}
Вывод, который я вижу, является
Constructor A 3
COPY constructor
MOVE constructor
Constructor A 5
MOVE constructor
MOVE constructor
Constructor A 6
MOVE constructor
MOVE constructor
MOVE constructor
У меня есть сомнения по поводу second call of fun. Оба конструктора перемещения используются во время
v.push_back(std::move(temp));
Как это работает, что никакой конструктор перемещения не используется для создания param of fun? В первом случае вызывается конструктор копирования, поэтому я предполагаю, что во время второго вызова fun move должен быть вызван конструктор. Мой следующий вопрос заключается в том, как это работает в first call of fun
v.push_back(std::move(temp));
вызывает только один конструктор перемещения, а второй call of fun вызывает 2 конструктора перемещения. Одна и та же строка вызывает конструктор перемещения 3 раза во время вызова fun2. Почему?
РЕДАКТИРОВАТЬ: Благодаря комментарию я добавил v.reserve (10), и теперь результаты выглядят намного лучше
Constructor A 3
COPY constructor
MOVE constructor
Constructor A 5
MOVE constructor
Constructor A 6
MOVE constructor
Остался только один вопрос. Как получается, что caling
fun(A(5))
не влияет ни на один конструктор? Это из-за оптимизации возвращаемого значения?
Комментарии:
1. Используйте
v.reserve(10);
перед вашими тестами, и ваш результат будет другим. cpp.sh/746u2. IIRC: Когда вы объявляете новый экземпляр
A
внутри вызова функции, это неявно является ссылкой перемещения. Посколькуfun2
ожидается ссылка на перемещение, там также вызывается другой конструктор перемещения.3. Тот факт, что f (A (5)) вызывает только один конструктор перемещения, действительно связан с оптимизацией возвращаемого типа (спецификация 12.8), A (5) создается в f parmeter temp.