2010-06-12 11 views
10

En C++ 11, los métodos pueden sobrecargarse con independencia de si la expresión que denota el objeto al que se llama el método es un valor l o un valor r. Si devuelvo *this desde un método llamado a través de un valor r, ¿necesito explícitamente move de *this o no?¿Mover desde * esto en un método rvalue?

Foo Foo::method() && 
{ 
    return std::move(*this); // Is this move required or not? 
} 

Por desgracia, no puedo simplemente probar esto en mi compilador g ++ ya no soporta esta función hasta el momento :(

+0

Espero que se requiera el 'movimiento', ya que' this' es un valor de r nombrado, similar a si una función toma un parámetro rvalue. Pero no hacer una respuesta ya que no puedo citar el capítulo y el versículo en él :) – jalf

+0

@jalf: Y yo esperaría que la mudanza sea necesaria ya que generalmente '* E' es un lvalue, pero quién sabe :) Y tengo nunca he escuchado hablar de valores de nombre antes. Estas seguro acerca de esto"? (¡sin juego de palabras!) – fredoverflow

+0

Un rvalue con nombre es un nuevo término introducido para eliminar la ambigüedad de las llamadas sobrecargadas que implican referencias. p.ej. si tenemos 'foo (X & x)' y 'foo (X && x)', ¿qué llama 'foo (someX)', es decir 'someX' an' X & 'o' X && '? La respuesta es 'X &' porque 'someX' tiene un nombre; se trata de un valor r nombrado, que es un' X & '. Si llamamos a 'foo (someX + something)', entonces sería un 'X &&' porque las expresiones no tienen "nombres". –

Respuesta

4

El tipo de *this es siempre un valor-i:

§9.3.2 [class.this] p1

En el cuerpo de una función miembro no estática (9.3), la palabra clave this es una expresión prvalue cuyo valor es la dirección del objeto para el que se llama a la función. El tipo de this en una función miembro de una clase X es . [...]

§5.3.1 [expr.unary.op] p1

El unario operador * realiza indirección: la expresión a la que se aplica será de un puntero a un tipo de objeto, o un puntero a una tipo de función y el resultado es un lvalue que se refiere al objeto o función a la que apunta la expresión.

Por lo tanto, necesitará std::move si desea invocar el constructor de movimientos.

El siguiente fragmento de código muestra que:

#include <iostream> 
#include <utility> 

struct test{ 
    test(){} 
    test(test const&){ std::cout << "copy ctor // #1\n"; } 
    test(test&&){ std::cout << "move ctor // #2\n"; } 

    test f_no_move() &&{ return *this; } 
    test f_move() &&{ return std::move(*this); } 
}; 

int main(){ 
    test().f_no_move(); // #1 
    test().f_move(); // #2 
} 

Usando Clang 3.1 (el único compilador que sé que implementa Ref-calificadores), me sale el siguiente resultado:

$ ruido metálico ++ -std = C++ 0x = -stdlib libC++ -pedantic -Wall T.cpp
$ ./a.out
copia ctor // # 1
movimiento ctor // # 2

Cuestiones relacionadas