2016-12-29 8 views
1
class N { 
public: 
    N() = default; 
    N(const N& n) { std::cout << "N copy\n"; }; 
private: 
    char c; 
}; 

class H { 
public: 
    H() = default; 
    H(H&) { std::cout << "H copy\n"; } 
    H(H&&) = default; 
private: 
    N n; 
}; 

int main() { 
    N n1, n2 = std::move(n1); 
    H h1, h2 = std::move(h1); 
} 

В VS2016 я определяю класс N, чтобы увидеть, что произойдет, если конструктор перемещения не будет определяться и не синтезироваться компилятором; и определите класс H, чтобы узнать, что произойдет, если удаленный конструктор перемещения по умолчанию будет удален.что-то запутанное о том, когда должен быть удален конструктор перемещения по умолчанию

В основной функции, выполняя первое заявление печатает «N копию», что означает, конструктор копирования называется, потому что нет никаких шагов конструктора в Н.

То, что я не могу понять, выполнив второе заявление «h2 = std :: move (h1)» также печатает «N copy».

Как я прочитал в C++ Primer (он основан на C++ 11), конструктор перемещения по умолчанию класса будет определен как удаленный, если класс имеет член, который определяет свой собственный конструктор копирования, но doesn ' t определить конструктор перемещения. Поскольку член n соответствует этому условию, конструктор перемещения H должен быть удален, «h2 = std :: move (h1)» должен вызывать конструктор копирования и, таким образом, печатать «H copy».

Однако напечатан только «N копия», что означает, что конструктор копирования H не вызывается, но вызывается конструктор копирования N. Зачем?


Вот что я думаю:

Компилятор все еще синтезируется конструктор перемещения для Н, и она работает так:

H(H&& h) :n(std::move(h.n)) {} 

Здесь конструктор движение пытается переместить член п, и точно так же, как в «N n1, n2 = std :: move (n1);», вызывается конструктор копирования N, таким образом печатается «N копия».


Это объяснение имеет смысл, но согласно C++ Primer, перемещение по умолчанию конструктор ч должен быть определен как удаление. Это конструктор копирования H, который должен быть вызван.

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

+0

Это [основная проблема 1402] (https://wg21.link/CWG1402). –

+0

Спасибо, теперь я понимаю, что это какая-то модификация, внесенная C++ 14. – Dardai

ответ

1

Что вас удивило? У вас есть конструктор перемещения по умолчанию для H, и он будет вызывать конструкторы move или copy для всех его членов. Существует только один элемент, тип N, который не имеет конструктора перемещения - поэтому вызывается конструктор копирования N. Вот почему вы видите распечатку.

+0

Поскольку в соответствии с C++ Primer конструктор перемещения по умолчанию для H должен быть определен как delete, но результат указывает, что он не удален, поэтому я удивлен. – Dardai

+0

Спасибо, теперь я понимаю, что это какая-то модификация, внесенная C++ 14 – Dardai

 Смежные вопросы

  • Нет связанных вопросов^_^