C++ à l'aide de copier-ctor lorsque l'opérateur=() est utilisé exactement comment cela fonctionne?

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

Question

Quelles sont exactement les règles pour le C++ de la conversion d'un operator=() affectation à un secteur de la construction?Comme Foo foo = bar sera fait appel Foo constructeur acceptant la barre comme un argument, si elle existe.J'ai cherché sur google comment cela fonctionne, mais n'arrive pas à trouver quoi que ce soit.

Je vais avoir un problème de comprendre pourquoi l'affectation ci-dessous tente de prendre un constructeur, mais ne prenant pas le évidemment correcte:HandlePtr( TYPE et de ressources ).Construction à l'aide de la construction réelle de la syntaxe fonctionne très bien, mais pas avec l'opérateur d'affectation.

code (évidemment modifiés par souci de concision):

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;
}

erreurs:

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
Était-ce utile?

La solution

Vous êtes négliger le fait que dans le déclaration:

T t = u;

ce n'est pas l'opérateur d'affectation. t = u; n'est pas une sous-expression d'une déclaration.La seule expression est ici u;et le résultat de l'évaluation de l'expression u est utilisée comme initialisation de l'objet t d'être déclaré.

Si u a type T, puis t la copie est construit à partir de u.

Si u n'a pas de type T, puis u la première doit être converti en type T.Cela crée une rvalue de type T.

Vous n'avez pas tous les constructeurs qui acceptent une rvalue, de sorte T t = u;, et la identique T t = T(u); les deux échouent.Cependant, T t(u) réussit, car aucun rvalue est créé;la valeur u est utilisé comme argument du constructeur T(U &).

Simplifiée exemple de code:

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 
}

Normalement, vous devriez utiliser const & en tant que paramètre pour la copie des constructeurs et des opérateurs d'affectation;tous ces "fail" cas "OK" , comme une rvalue peut être lié à une référence const.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top