C++ mediante copia-cto r cuando el operador=() que se usa es exactamente cómo funciona esto?

StackOverflow https://stackoverflow.com//questions/23025259

Pregunta

¿Qué son exactamente las reglas de C++ la conversión de un operador=() la asignación a una construcción?Como Foo foo = bar realmente llamada Foo constructor de la aceptación de la barra como un argumento, si es que existe.He buscado en google de cómo funciona esto, pero parece que no puede encontrar nada.

Yo estoy teniendo un problema para averiguar por qué la asignación de abajo está tratando de tomar un constructor, pero no tomar el obviamente correcta:HandlePtr( TIPO y de recursos ).La construcción en la utilización real de la construcción de la sintaxis funciona bien, pero no con el operador de asignación.

código (obviamente editado por brevedad):

template< typename TYPE >
class HandlePtr {
public:
    HandlePtr( void ) = default;
    HandlePtr( HandlePtr< TYPE >& other ) = default;
    HandlePtr( TYPE& resource ) {} // generally I would make this explicit, but for testing purposes I took it out
    ~HandlePtr( void ) = default;

public:
    HandlePtr<TYPE>& operator=( TYPE& resource ) { return *this; }
    HandlePtr<TYPE>& operator=( HandlePtr<TYPE>& other ) { return *this; }
};

int main ( void ) {
    int x = 5;
    HandlePtr< int > g( x ); // works
    HandlePtr< int > i;i = x; // works
    HandlePtr< int > h = x; // doesn't work

            // also tried this just out of curiosity:
    HandlePtr< int > h = HandlePtr< int >( x ); // also does not work

    return 0;
}

errores:

shit.cpp: In function ‘int main()’:
try.cpp:19:24: error: no matching function for call to ‘HandlePtr<int>::HandlePtr(HandlePtr<int>)’
   HandlePtr< int > h = x; // doesn't work
                        ^
try.cpp:19:24: note: candidates are:
try.cpp:7:3: note: HandlePtr<TYPE>::HandlePtr(TYPE&) [with TYPE = int]
   HandlePtr( TYPE& resource ) {} // generally I would make this explicit, but for testing purposes I took it out
   ^
try.cpp:7:3: note:   no known conversion for argument 1 from ‘HandlePtr<int>’ to ‘int&’
try.cpp:6:3: note: HandlePtr<TYPE>::HandlePtr(HandlePtr<TYPE>&) [with TYPE = int]
   HandlePtr( HandlePtr< TYPE >& other ) = default;
   ^
try.cpp:6:3: note:   no known conversion for argument 1 from ‘HandlePtr<int>’ to ‘HandlePtr<int>&’
try.cpp:5:3: note: HandlePtr<TYPE>::HandlePtr() [with TYPE = int]
   HandlePtr( void ) = default;
   ^
try.cpp:5:3: note:   candidate expects 0 arguments, 1 provided
try.cpp:20:20: error: redeclaration of ‘HandlePtr<int> h’
   HandlePtr< int > h = HandlePtr< int >( x ); // also does not work
                    ^
try.cpp:19:20: error: ‘HandlePtr<int> h’ previously declared here
   HandlePtr< int > h = x; // doesn't work
¿Fue útil?

Solución

Estás con vistas a que en el declaración:

T t = u;

este no es el operador de asignación. t = u; no es una sub-expresión de una declaración.La única expresión que aquí se u;y el resultado de la evaluación de la expresión u se utiliza como inicializador de objeto t está declarada.

Si u tiene el tipo T, a continuación, t es copia-construido a partir de u.

Si u no tiene el tipo T, a continuación, u primero debe ser convertido al tipo T.Esto crea un r-value de tipo T.

Usted no tiene ningún constructor que acepta un r-value, por lo que T t = u;, y los mismos T t = T(u); ambos errores.Sin embargo, T t(u) tiene éxito porque no hay r-value es creado;el valor u se utiliza como argumento para el constructor T(U &).

Simplificado código de ejemplo:

struct T
{
    T(int &);
    T(T&);
    T();
    T &operator=(int &);
};

int main()
{
    int x = 5;
    T g(x);   // OK, T(int &)
    T g2(5);   // fail, looks for T(int const &)
    T i;      // OK, T()
    i = x;    // OK, T::operator=(int&)
    T h3 = i; // OK, T(T&)
    T h1 = T(x);    // fail, looks for T(T const &)
    T h2 = x;       // fail, identical to previous line 
}

Normalmente, usted debe utilizar const & como el parámetro para copiar los constructores y operadores de asignación;a continuación, todos estos "fail" de los casos se convierten en "ACEPTAR" , como un r-value puede ser obligado a una constante de referencia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top