C++ à l'aide de copier-ctor lorsque l'opérateur=() est utilisé exactement comment cela fonctionne?
-
21-12-2019 - |
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
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.