Почему конструктор перемещения / оператор присваивания в C ++ 11 не работает должным образом

#include <iostream>

using namespace std;

struct A
{
A()
{
cout << "A()" << endl;
}

~A()
{
cout << "~A()" << endl;
}

A(A&&)
{
cout << "A(A&&)" << endl;
}

A& operator =(A&&)
{
cout << "A& operator =(A&&)" << endl;
return *this;
}
};

struct B
{
// According to the C++11, the move ctor/assignment operator
// should be implicitly declared and defined. The move ctor
// /assignment operator should implicitly call class A's move
// ctor/assignment operator to move member a.
A a;
};

B f()
{
B b;

// The compiler knows b is a temporary object, so implicitly
// defined move ctor/assignment operator of class B should be
// called here. Which will cause A's move ctor is called.
return b;
}

int main()
{
f();
return 0;
}

Мой ожидаемый результат должен быть:

A()
A(A&&)
~A()
~A()

Тем не менее, фактический вывод: (Компилятор C ++: Visual Studio 2012)

A()
~A()
~A()

Это ошибка VC ++? или только мое недоразумение?

8

Решение

В соответствии с этот блог, VC ++ 2012 в настоящее время реализует N2844 + DR1138, но нет N3053. В результате компилятор не неявное создание конструкторов перемещения или операторов присваивания для вас. Если вы добавите явное значение по умолчанию и переместите конструкторы в B тогда вы получите ожидаемый результат.

14

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

Visual C ++ 2012 не реализует окончательную спецификацию C ++ 11 для rvalue ссылок и операций перемещения (спецификация менялась несколько раз в процессе стандартизации). Вы можете узнать больше информации в блоге команды разработчиков Visual C ++, «Возможности C ++ 11 в Visual C ++ 11», под Rvalue ссылки.

В вашем примере это проявляется двумя способами:

  • определение пользовательских операций перемещения в A не подавляйте неявно объявленные операции копирования.

  • не существует неявно определенных операций перемещения для B,

7

Я не думаю, что генерация копии ctor предотвращается объявлением конструктора перемещения. … и кажется, что компилятор предпочитает конструктор копирования, а не конструктор перемещения.

На самом деле, согласно пункту 7 12.8 [class.copy], наличие конструктора перемещения должно препятствовать конструктору копирования:

Если определение класса не объявляет явно конструктор копирования, он объявляется неявно. Если определение класса объявляет конструктор перемещения или оператор присваивания перемещения, неявно объявленный конструктор копирования определяется как удаленный; в противном случае он определяется как дефолтный (8.4).

Тем не менее, детали построения перемещения были изменены до поздней стадии процесса, и кажется, что VC ++ не реализует фактический стандарт, но более раннюю версию.

1
По вопросам рекламы [email protected]