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:
-
operator =
restricciónoperator =
a lvalues (respuesta de TemplateRex) - Activación de movimiento para miembros (básicamente esta respuesta)
-
operator &
restricciónoperator &
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).