2016-09-01 2 views
1

Здесь creator() возвращает указатель на X, который я разыскиваю и перехожу к foo. Поскольку это rvalue, следует использовать семантику перемещения, правильно? Но когда я запускаю его, я нахожу, что вызывается foo (X &).C++: почему foo (X &) вызывается вместо foo (X &&)?

#include <iostream> 
using namespace std; 

struct X { 
     int i; 
}; 

void foo(X& x) { 
     cout << "foo(X&)" << endl; 
} 

void foo(X&& x) { 
     cout << "foo(X&&)" << endl; 
} 

struct X* creator() { 
     return new X {5}; 
} 

main() { 
     X x{5}; 
     foo(*creator()); // prints foo(X&) 
} 
+1

http://en.cppreference.com/w/cpp/language/operator_member_access#Built-in_indirection_operator – chris

ответ

3

creator() возвращает указатель.

Выделение этого указателя дает вам значение lvalue. Выражение указателя приводит к lvalue. В конце концов, если p является указателем, вы можете назначить ему: *p=some_value, и вы можете назначить только lvalue, поэтому оно должно быть lvalue.

Вы сбиты с толку двумя вещами. Верно, что функция возвращает значение r. Но вы не передаете то, что возвращает функция. Функция возвращает указатель, и вы разыскиваете указатель, что приводит к lvalue.

+0

Я вижу. Использование std :: move делает трюк – user1299784

+1

* ", и вы можете назначать только lvalue, поэтому оно должно быть lvalue" * - Это не относится к типам классов. –

+0

Или константные указатели. – Barry

3

Это полезно думать о вещах, с точки зрения идентичности и подвижности:

  • Has идентичность и не могут быть перемещены из? lvalue
  • Имеет личность и может быть перенесен с? xvalue
  • Нет личности? prvalue

Выполнение разыменования указателя дает выражение, которое имеет идентификатор, из которого нельзя перенести, поэтому это значение lvalue. Следовательно, он соответствует перегрузке X&.

Если вы хотите вызвать другую перегрузку, вам нужно будет аннотировать выражение, чтобы указать, что его можно безопасно перенести. Это то, для чего стоит std::move. Как только вы это сделаете, выражение станет xvalue и теперь соответствует перегрузке X&&.