2015-12-17 2 views
0

Я читаю this ответ о перемещении семантики и придумать проблему. Он описывает так называемый перемещение и своп идиома:Переместить семантический и объект тип параметра

unique_ptr& operator=(unique_ptr source) // note the missing reference 
{ 
    std::swap(ptr, source.ptr); 
    return *this; 
} 

Поскольку оператор присваивания двигаться должны работать на RValue ссылки, я думал, что это приемлемо передать ссылку RValue в качестве аргумента. Вот пример:

#include <iostream> 

struct A { 
    A(){ } 
    virtual ~A(){ } 
    A(A&&){ } 
}; 

void foo(A a){ 
    std::cout << "foo(A)" << std::endl; 
} 

int main() 
{ 
    foo(*new A); 
} 

DEMO

Но компилятор предупреждает меня, что он пытался скопировать объект ссылки и не потому, что копия-конструктор удаляется. Я не знаю, почему это правильно в примере с unique_ptr. Объект должен быть скопированы когда мы вызываем функцию, так что нет никакого смысла двигаться семантических.

Не могли бы вы немного объяснить это?

+4

Я не уверен, насколько сильным является ваше понимание C++, '* new T' обычно является подарком не понимающей семантики значения. То, что вы хотели бы в реальной жизни, это 'foo (A {});' но, конечно же, вы знаете это, и это просто академический. –

+1

'* new A' - это значение lvalue. Он обозначает место памяти, в котором хранится объект. Чтобы переместиться, вам нужно написать 'std :: move (* new A)' (который будет утечка памяти) –

+0

«' * new A' », как вы собираетесь« удалить », что' A'? – emlai

ответ

2

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

void f(std::unique_ptr<Foo> p); 
std::unique_ptr<Foo> p; 
f(p); // error 
f(std::move(p)); // OK 

В вашем примере, можно сделать следующее:

foo(std::move(*new A)); 

но *new A само по себе не является возможным аргументом, так как разыменования указателя всегда производит именующее выражение.

4

Выражение *(new A) не является значением rvalue.

Общее правило (не the actual rule, просто quickie), для каких выражений являются значения rvalue: это либо временное, либо то, что вы явно называете std::move. А *(new A) не является временным. И вы не набрали на нем move. Так что это не rvalue.

Попробуйте это вместо A().

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