teorico programas programacion practico poo paso orientada objetos ejemplos ejemplo comandos codigo clases c++ c++11 overloading rvalue-reference qualifiers

c++ - programas - ¿Cuál es el caso de uso para sobrecargar funciones miembro en calificadores de referencia?



ejemplos de programas en c++ pdf (4)

C ++ 11 permite sobrecargar funciones de miembros basadas en calificadores de referencia:

class Foo { public: void f() &; // for when *this is an lvalue void f() &&; // for when *this is an rvalue }; Foo obj; obj.f(); // calls lvalue overload std::move(obj).f(); // calls rvalue overload

Entiendo cómo funciona esto, pero ¿qué es un caso de uso para ello?

Veo que N2819 propuso limitar la mayoría de los operadores de asignación en la biblioteca estándar para validar objetivos (es decir, agregar calificadores de referencia " & " a los operadores de asignación), pero esto fue rechazado . Entonces ese fue un caso de uso potencial en el que el comité decidió no aceptarlo. Entonces, de nuevo, ¿qué es un caso de uso razonable?


Por un lado, puede usarlos para evitar que las funciones que son semánticamente absurdas llamen a las llamadas temporales, tales como operator= o funciones que cambian el estado interno y devuelven el void , agregando & como un calificador de referencia.

Por otro lado, puede usarlo para optimizaciones, como mover un miembro fuera del objeto como valor de retorno cuando tiene una referencia de valor real, por ejemplo, una función getName podría devolver una std::string const& o std::string&& dependiendo en el calificador de referencia.

Otro caso de uso podría ser operadores y funciones que devuelven una referencia al objeto original como Foo& operator+=(Foo&) que podría especializarse para devolver una referencia rvalue, haciendo que el resultado sea movible, lo que de nuevo sería una optimización.

TL; DR: Úselo para evitar el uso incorrecto de una función o para la optimización.


Si f () necesita una temperatura Foo que sea una copia de esto y modificada, puede modificar la temperatura en this lugar mientras que de otra manera no puede


En una clase que proporciona referencias-getters, la sobrecarga ref-qualifier puede activar la semántica de movimiento al extraer de un valor r. P.ej:

class some_class { huge_heavy_class hhc; public: huge_heavy_class& get() & { return hhc; } huge_heavy_class const& get() const& { return hhc; } huge_heavy_class&& get() && { return std::move(hhc); } }; some_class factory(); auto hhc = factory().get();

Esto parece un gran esfuerzo para invertir solo para tener la sintaxis más corta

auto hhc = factory().get();

tener el mismo efecto que

auto hhc = std::move(factory().get());

EDIT: encontré el documento de propuesta original , proporciona tres ejemplos motivadores:

  1. operator = restricción operator = a lvalues ​​(respuesta de TemplateRex)
  2. Activación de movimiento para miembros (básicamente esta respuesta)
  3. operator & restricción operator & valores l. Supongo que esto es sensato para asegurar que el "pointee" tenga más probabilidades de estar vivo cuando el "puntero" sea eventualmente desreferenciado:

struct S { T operator &() &; }; int main() { S foo; auto p1 = &foo; // Ok auto p2 = &S(); // Error }

No puedo decir que haya usado personalmente un operator& sobrecarga.


Un caso de uso es prohibir la asignación a los temporales

// can only be used with lvalues T& operator*=(T const& other) & { /* ... */ return *this; } // not possible to do (a * b) = c; T operator*(T const& lhs, T const& rhs) { return lhs *= rhs; }

mientras que no usar el calificador de referencia dejaría la elección entre dos males

T operator*(T const& lhs, T const& rhs); // can be used on rvalues const T operator*(T const& lhs, T const& rhs); // inhibits move semantics

La primera opción permite la semántica de movimiento, pero actúa de manera diferente en los tipos definidos por el usuario que en los integrados (no hace lo que hacen los ints). La segunda opción detendría la asignación, pero eliminaría la semántica del movimiento (posible rendimiento alcanzado, por ejemplo, la multiplicación de la matriz).

Los enlaces de @dyp en los comentarios también proporcionan una discusión extensa sobre el uso de la otra ( && ) sobrecarga, que puede ser útil si desea asignar referencias (ya sea lvalue o rvalue).