2014-12-18 6 views
3

В строке, прокомментированной ***, почему вызван конструктор копии Bar? input_bar - это ссылка на rvalue, поэтому я ожидаю, что будет вызываться конструктор перемещения. Он преобразовал в ссылку lvalue? Я могу сделать вызов конструктора перемещения, если я изменю эту строку на bar_(std::move(input_bar)).Реализация конструктора перемещения

#include <iostream> 
#include <array> 
#include <memory> 

class Bar 
{ 
public: 
    Bar(const Bar& bar) 
    { 
    std::cout << "copy constructor called" << std::endl; 
    } 

    Bar(Bar&& bar) 
    { 
    std::cout << "move constructor called" << std::endl; 
    } 
}; 

class Foo 
{ 
public: 
    Foo(Bar&& input_bar) : 
    bar_(input_bar) // *** 
    { 
    } 
    Bar bar_; 
}; 

int main() 
{ 
    Bar bar; 
    Foo foo(std::move(bar)); 
    return 0; 
} 
+0

См. Http://stackoverflow.com/q/27554296/981959 –

ответ

8

Как только у субъекта есть имя, это явно значение! Если у вас есть имя для ссылки rvalue, объект с именем не rvalue, а lvalue. Все дело в том, что вы знаете, что этот объект ссылается на rvalue, и вы можете законно перемещать его содержимое.

Если вы хотите просто переслать rvalueness к следующей функции вы называете, вы бы использовать std::move(), например .:

Foo(Bar&& bar): bar_(std::move(bar)) {} 

Без std::move() Rvalue считается собственностью конструктора. С std::move() он освобождает право собственности и передает его следующей функции.

+0

Стандартные ссылки будут _nice_, хотя и не обязательно необходимы. –

+0

Я вижу. Мне помогает понять, что ссылка rvalue (т.е. 'input_bar') является ссылкой на rvalue, следовательно, это lvalue. Я знаю, это звучит очевидно ... –

2

Вы должны двигаться РГКР:

Foo(Bar&& input_bar) : 
    bar_(std::move(input_bar)) // *** 
    { 
    } 

Полагают, что когда-то мы на самом деле использовать RHR, следует рассматривать как semantially из области видимости. Принуждение вас использовать std::move позволяет следующий код, чтобы не быть неопределенными:

Foo(Bar&& input_bar) { 
    std::cout << input_bar.baz << std::endl;//not undefined 
    bar_ = Bar{std::move(input_bar)};//input_bar is now essentailly destroyted 
    //std::cout << input_bar.baz << std::endl;//Undefined behavior, don't do this 
} 

Общее правило заключается в том, что только вещи, без имен на самом деле могут быть использованы в качестве ООТ в ... ООТ в качестве аргументов имеют имена, и, таким образом, будет следует рассматривать как LHR, пока вы не назовете на них функцию.

+0

Да, поскольку ОП уже обнаружен без этого ответа. ОП просит объяснить, почему это необходимо, почему этот эффект не достигается, если не используется «std :: move». – hvd

+0

@hvd oo ok отредактирует – IdeaHat

+0

Независимо от того, создает ли эта последняя строка неопределенное поведение, зависит от того, что такое 'baz'. Для большинства типов я бы не ожидал, что это неопределенное поведение, просто неопределенное. –

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

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