Pergunta

Um de vocês pode explicar por que a seguinte parte do código não é compilada?

#include <iostream>

using namespace std;

class Foo
{
public:
  Foo() { cout << "Foo::Foo()" << endl << endl; }
  Foo& operator=(const Foo&) { cout << "Foo::operator=(const Foo&)" << endl << endl; }
private:
  Foo(const Foo& b) { *this = b; cout << "Foo::Foo(const Foo&)" << endl << endl; }
};

int main()
{
  Foo foo;

  foo = Foo();
}

O erro que recebo:

$ g++ -o copy_ctor_assign copy_ctor_assign.cc && ./copy_ctor_assign
copy_ctor_assign.cc: In function 'int main()':
copy_ctor_assign.cc:10: error: 'Foo::Foo(const Foo&)' is private
copy_ctor_assign.cc:17: error: within this context

Nota: Quando eu removo o privado: Palavra -chave A compila de código, mas o ctor não é chamado. Então, por que errar quando é privado?

Não tenho certeza se é importante, mas estou usando:

$ g++ --version
g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-44)
Copyright (C) 2006 Free Software Foundation, Inc.
Foi útil?

Solução

Você está inicializando uma referência temporária.
Os estados padrão:
O temporário deve ser inicializado (8.5.3 par 5) "Usando as regras para uma inicialização de cópia de não referência (8.5)".

A construção da cópia é removida para o temporário (permitido pelo padrão. 12.8 par 5).
No entanto, o padrão afirma claramente (12.2 par 1):
"Mesmo quando a criação do objeto temporário é evitada (12,8), todas as restrições semânticas devem ser respeitadas como se o objeto temporário fosse criado. [Exemplo: mesmo que o construtor de cópias não fosse chamado, todas as restrições semânticas, como a acessibilidade (Cláusula 11), deve ser satisfeito.] "

(Além disso, ao procurar a citação certa, achei isso duplicado :)

Editar: Adicionando localização relevante do padrão

Outras dicas

Esse código compila com o GCC 4.3.3 e 4.4.1. Talvez seja apenas um bug no GCC 4.1?

Supondo que o código que você postou seja o único código no projeto, e não há passagem secreta do FOOS por valor em qualquer lugar, tudo o que posso imaginar é que o GCC está otimizando

Foo foo;
foo = Foo();

para

Foo foo = Foo();

... o que não é dono, pois o primeiro formulário é uma construção padrão e uma tarefa, enquanto o segundo é equivalente a

Foo foo(Foo());

... que é claramente uma construção de cópia. Se eu estiver certo, o construtor de cópias não está sendo executado porque o GCC pode otimizar o redundante temporário; Isso é permitido pela especificação C ++.

Em geral, não é uma boa idéia ter operadores de tarefas e copiar construtores em diferentes níveis de proteção; Como você viu, os resultados podem ser inintivos.

Cópia ctor é chamada quando:

  1. passando um objeto por valor como parâmetro para uma função,
  2. retornando um objeto de uma função.

Então, você certamente está fazendo um ou ambos os casos em algum lugar do seu código. Você deve definir cópia como público ou evitar os 2 casos anteriores.

Cópia do construtor seria chamado se você escrever

Foo foo; // normal constructor
Foo foo1(foo); //copy constructor

No seu caso, primeiro o construtor padrão é chamado e, em seguida, o Método Operador =.

#include <iostream>

using namespace std;

class Foo
{
public:
  Foo() { cout << "Foo::Foo()" << endl << endl; }
  Foo& operator=(const Foo&) { cout << "Foo::operator=(const Foo&)" << endl << endl; }
  Foo(const Foo& b) { *this = b; cout << "Foo::Foo(const Foo&)" << endl << endl; }
};

int main()
{
  Foo f1;// default constructor called

  Foo f2 = f1; //copy constructor called
}

Verifique isso, em Foo f2=f1; ( f2 é criado usando o copy construtor)

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