пожалуйста, посмотрите на следующий пример кода:Почему вместо конструктора перемещения вызывается экземпляр конструктора?
#include <iostream>
struct Foo {
Foo() { std::cout << "Default!\n"; }
Foo(const Foo& foo) { std::cout << "Copy!\n"; }
Foo(Foo&& foo) { std::cout << "Move!\n"; }
};
struct Bar {
Foo foo;
Bar() {}
Bar(Bar &that) : foo(that.foo) {}
Bar(Bar &&that) : foo(std::move(that.foo)) {}
};
Bar f() {
Bar bar;
return bar;
}
int main() {
Bar bar(f());
}
I'am ожидает, что выход из этого кода должно быть:
Default!
Move!
но то, что я получаю:
Default!
Copy!
Я не вижу причин, по которым вместо конструктора перемещения вызывается конструктор копирования. Если я поставлю ключевое слово const
перед Bar &that
в объявлении конструктора копирования struct Bar
, у меня есть правильный результат. Я знаю, что во многих случаях лучше взять ссылку на константу lvalue, а не только ссылку lvalue для конструкторов копирования, но я просто хочу знать причину, почему это произошло.
Почему в этом примере Bar &
был предпочтительнее, чем Bar &&
, хотя возвращаемое значение f()
следует рассматривать как prvalue? Почему ключевое слово const
решает проблему? const
действительно решает проблему? Связано ли это с RVO (Оптимизация возвращаемого значения)? Или это просто ошибка компилятора?
Я проверил этот пример на Visual C++ November 2012 CTP.
Я нашел аналогичный вопрос здесь:
Copy constructor is being called instead of the move constructor
Но я до сих пор не могу понять, почему.
Может ли кто-нибудь мне помочь?
Невозможно воспроизвести. С GCC я просто получаю 'Default!' (Sane NRVO на работе), с '-fno-elide-constructors' я получаю ожидаемый' Default! Переехать! Move! '. Может быть, компилятор b^Hshortcoming? –
изменить 'Bar (Bar & the)' '' Bar (const Bar & that) '. –
@KerrekSB 1. Я понимаю случай NRVO. Но почему ожидаются два, а не только один «Move!», Когда разрешение копирования отключено? 2. Вы говорите, что это всего лишь ошибка компилятора, который я использовал? Спасибо в любом случае. –