Я пытаюсь проверить РВО а также Rvalue ссылка. Вот код:
#include <iostream>
using namespace std;
class B{
public:
int i;
B(){
i = 0;
cout << "B() " << i << endl;
}
B(const B& b){
i = 1;
cout << "B(const B&) " << i << endl;
}
B(const B&& b){//if remove this constructor, then call B(const B& b)
i = 2;
cout << "B(const B&&) " << i << endl;
}
~B(){
cout << "~B() " << i << endl;
}
};
B f(){
B b;
return b;
}
int main(){
B b = f();
return 0;
}
Выход:
B() 0
B(const B&&) 2
~B() 0
~B() 2
Среда: WIN8, Visual Studio 2012 Express
Это означает, что переместить конструктор: B (const B&&) называется.
Подняты два вопроса:
Если я удалю B (const B&&), затем B (const B&) называется. Странный вывод:
B () 0
B (const B&) 1
~ B () 0
~ B () 1
Вот ссылки, которые я нашел:
РЕДАКТИРОВАТЬ:
переместить конструктор должно быть B (B&&). Дело в том, почему конструктор перемещения называется НЕ конструктор копирования.
Почему РВО здесь не применяется?
Это не просто выполнение оптимизаций. G ++ использует RVO здесь при использовании -O2
, Вы должны включить оптимизацию на вашем компиляторе, чтобы проверить это. Однако обратите внимание, что даже если некоторые компиляторы могут применять RVO, это не обязательно, поэтому вы можете увидеть разные результаты при использовании разных компиляторов.
Почему НЕ вызывать конструктор перемещения: B (const B&)?
Это конструктор копирования. Он вызывает конструктор перемещения, который здесь лучше подходит.
Если я удаляю B (const B&&), то B (const B&) называется. Weird!
Нет, это не странно. Конструктор перемещения не будет неявно определен компилятором, если вы определите конструктор копирования. Следовательно, компилятор выбирает конструктор копирования, поскольку конструктор перемещения недоступен.
Обратите внимание, что ваш конструктор перемещения должен иметь неконстантную ссылку:
B(B&& b) {
// ...
}
В противном случае вы бы просто сделали то же самое, что и в конструкторе копирования.
Других решений пока нет …