#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 ++? или только мое недоразумение?
В соответствии с этот блог, VC ++ 2012 в настоящее время реализует N2844 + DR1138, но нет N3053. В результате компилятор не неявное создание конструкторов перемещения или операторов присваивания для вас. Если вы добавите явное значение по умолчанию и переместите конструкторы в B
тогда вы получите ожидаемый результат.
Visual C ++ 2012 не реализует окончательную спецификацию C ++ 11 для rvalue ссылок и операций перемещения (спецификация менялась несколько раз в процессе стандартизации). Вы можете узнать больше информации в блоге команды разработчиков Visual C ++, «Возможности C ++ 11 в Visual C ++ 11», под Rvalue ссылки.
В вашем примере это проявляется двумя способами:
определение пользовательских операций перемещения в A
не подавляйте неявно объявленные операции копирования.
не существует неявно определенных операций перемещения для B
,
Я не думаю, что генерация копии ctor предотвращается объявлением конструктора перемещения. … и кажется, что компилятор предпочитает конструктор копирования, а не конструктор перемещения.
На самом деле, согласно пункту 7 12.8 [class.copy], наличие конструктора перемещения должно препятствовать конструктору копирования:
Если определение класса не объявляет явно конструктор копирования, он объявляется неявно. Если определение класса объявляет конструктор перемещения или оператор присваивания перемещения, неявно объявленный конструктор копирования определяется как удаленный; в противном случае он определяется как дефолтный (8.4).
Тем не менее, детали построения перемещения были изменены до поздней стадии процесса, и кажется, что VC ++ не реализует фактический стандарт, но более раннюю версию.