Pergunta

Eu escrevi o seguinte programa de teste quando o construtor de cópia é chamado e quando o operador de atribuição é chamado:


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

Isto resulta na seguinte saída (acabou de adicionar linhas empy para torná-lo mais compreensível):

doronw@DW01:~$ ./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


O segundo e terceiro conjunto se comportam como esperado, mas no primeiro set, o construtor de cópia é chamado, mesmo que o operador de atribuição é usado.

É esta parte comportamento do C ++ padrão ou apenas uma otimização do compilador inteligente (estou usando gcc 4.4.1)

Foi útil?

Solução

Sem operador de atribuição é usado no primeiro teste caso. Ele só usa a forma de inicialização chamado de "cópia de inicialização". Cópia de inicialização não considera construtores explícitos ao inicializar o objeto.

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

Copiar inicialização é usado nos casos que correspondem a conversões implícitas, onde não se chutar explicitamente fora de uma conversão, como em função argumento de passagem, e que retornam de uma função.

Outras dicas

C ++ padrão de 8,5 / 12

A inicialização que ocorre em passagem de argumento, retorno de função, gerar uma exceção (15.1), tratamento uma excepção (15,3), e initializer listas fechado-chave (8.5.1) é chamado copy-inicialização e é equivalente ao formulário

T x = a;

A inicialização que ocorre na nova expressões (5.3.4), static_cast expressões (5.2.9), funcionais as conversões de tipo notação (5.2.3), e inicializadores de base e dos membros (12.6.2) é chamado-inicialização direta e é equivalente ao formulário

T x(a);

Seu primeiro conjunto é de acordo com o C ++ padrão, e não devido a alguma otimização.

Secção 12.8 ([class.copy]) do C ++ padrão dá uma exemplo semelhante:

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

A última linha seria a única combinando seu caso.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top