2010-01-08 8 views
3

j'ai écrit le programme suivant pour tester lorsque le constructeur de copie est appelée et lorsque l'opérateur d'affectation est appelé:Les constructeurs de copie et Opérateurs d'affectation

 

#include 

class Test 
{ 
public: 
    Test() : 
     iItem (0) 
    { 
     std::cout << "This is the default ctor" << std::endl; 
    } 

    Test (const Test& t) : 
     iItem (t.iItem) 

    { 
     std::cout << "This is the copy ctor" << std::endl; 
    } 

    ~Test() 
    { 
     std::cout << "This is the dtor" << std::endl; 
    } 

    const Test& operator=(const Test& t) 
    { 
     iItem = t.iItem;  
     std::cout << "This is the assignment operator" << std::endl; 
     return *this; 
    } 

private: 
    int iItem; 
}; 

int main() 
{ 
    { 
     Test t1; 
     Test t2 = t1; 
    } 
    { 
     Test t1; 
     Test t2 (t1); 
    } 
    { 
     Test t1; 
     Test t2; 
     t2 = t1; 
    } 
} 

Il en résulte la sortie suivante (juste ajouté lignes empy pour le rendre plus compréhensible):

 
[email protected]:~$ ./test 
This is the default ctor 
This is the copy ctor 
This is the dtor 
This is the dtor 

This is the default ctor 
This is the copy ctor 
This is the dtor 
This is the dtor 

This is the default ctor 
This is the default ctor 
This is the assignment operator 
This is the dtor 
This is the dtor 


le deuxième et le troisième ensemble se comportent comme prévu, mais dans le premier jeu de la copie constru ctor est appelé même si l'opérateur d'affectation est utilisé.

Est-ce une partie de comportement du standard C++ ou tout simplement une optimisation intelligente du compilateur (j'utilise gcc 4.4.1)

Répondre

10

Aucun opérateur d'affectation est utilisé dans le premier cas de test. Il utilise simplement le formulaire d'initialisation appelé "copie initialisation". L'initialisation de la copie ne prend pas en compte les constructeurs explicites lors de l'initialisation de l'objet.

struct A { 
    A(); 

    // explicit copy constructor 
    explicit A(A const&); 

    // explicit constructor 
    explicit A(int); 

    // non-explicit "converting" constructor 
    A(char const*c); 
}; 

A a; 
A b = a; // fail 
A b1(a); // succeeds, "direct initialization" 

A c = 1; // fail, no converting constructor found 
A d(1); // succeeds 

A e = "hello"; // succeeds, converting constructor used 

initialisation de copie est utilisée dans les cas qui correspondent à des conversions implicites, où l'on n'a pas explicitement coup de conversion, comme en passant l'argument de la fonction, et le retour d'une fonction.

2

Votre premier ensemble est conforme à la norme C++, et non à une optimisation.

Section 12.8 ([class.copy]) du C++ standard donne un exemple similaire:

class X { 
    // ... 
public: 
    X(int); 
    X(const X&, int = 1); 
}; 

X a(1);  // calls X(int); 
X b(a, 0); // calls X(const X&, int); 
X c = b; // calls X(const X&, int); 

La dernière ligne serait celui qui correspond à votre cas.

3

C de type 8,5/12

L'initialisation qui se produit au passage d'argument , le retour de la fonction, lancer une exception (15.1), la manipulation une exception (15.3), et listes de initialiseur clos accolades (8.5.1) est appelée copy-initialisation et est équivalent à la forme

T x = a; 

l'initialisation qui se produit dans la nouvelle expressions (5.3.4), static_cast expressions (5.2.9), conversions de types de notation fonctionnels (5.2.3), et la base et membre initializers (12.6.2) est appelée -initialisation directe et est équivalent à le formulaire

T x(a);