C++ construtor de Cópia, temporários e cópia semântica
Pergunta
Para este programa
#include <iostream>
using std::cout;
struct C
{
C() { cout << "Default C called!\n"; }
C(const C &rhs) { cout << "CC called!\n"; }
};
const C f()
{
cout << "Entered f()!\n";
return C();
}
int main()
{
C a = f();
C b = a;
return 0;
}
a saída que eu vejo é:
Entered f()!
Default C called!
CC called!
Desde f()
é a devolver o valor, ele deve retornar um temporário.Como T a = x;
é T a(x);
, não é chamar o construtor de cópia para a construção de a
, com o temporário no passado como argumento?
Solução
Desde
f()
é a devolver o valor, ele deve retornar um temporário.ComoT a = x;
éT a(x);
, não é chamar o construtor de cópia para a construção dea
, com o temporário no passado como argumento?
Procurar Valor de Retorno de Otimização.Esta é ativada por padrão.Se você estiver no Windows, usando MSVC 2005+ você pode usar /Od
para desligar esta opção e obter o resultado desejado (ou -fno-elide-constructors
no GCC).Também, para ver MSVC este artigo.
12.8 Copiar objectos de classe
15 Quando determinados critérios forem atendidos, uma a implementação é permitido omitir o cópia de construção de um objeto de classe, mesmo se o construtor de cópia e/ou destruidor do objeto tem um lado efeitos.Em tais casos, o implementação trata a origem e o alvo da omitido operação de cópia simplesmente como duas formas diferentes de referindo-se ao mesmo objeto, e a a destruição do objeto ocorre em o posterior das vezes quando as duas os objetos teriam foi destruída sem a otimização.115 Este elision de cópia operações é permitida a seguintes circunstâncias (que pode ser combinado para eliminar vários cópias):
— em uma instrução return em uma função com uma classe de tipo de retorno, quando a expressão é o nome de um não-volátil automático de objetos com o mesmo cv-não qualificado como o tipo de tipo de retorno de função, a cópia a operação pode ser omitido por construção automática de objeto diretamente para o retorno da função valor — em um lance de expressão, quando o operando é o nome de um não-volátil automático de objetos, o operação de cópia do operando para o objeto de exceção (15.1) pode ser omitido ao construir o objeto automática diretamente para o objeto de exceção
— quando uma classe temporária objeto que tem não foi vinculado a uma referência (12.2) deve ser copiado para um objeto de classe com o mesmo cv-não qualificados tipo, a cópia a operação pode ser omitido por construindo o objeto temporário diretamente para o destino da omitido cópia
— quando o exceção-declaração de uma exceção manipulador (Cláusula 15) declara um objeto do mesmo tipo (exceto para cv-qualificação) como exceção objeto (15.1), a operação de cópia pode ser omitido, por tratar o exceção de declaração como um alias para o objeto de exceção se o significado de o programa será inalterado, exceto para a execução de construtores e destruidores para o objeto declarado por a exceção de declaração.
Nota:Ênfase minha
Outras dicas
Este é um exemplo de Otimização de valor de retorno (RVO) Recursos que seu compilador suporta.
Um construtor de cópia pode não ser chamado quando você retornar por valor.
Usar -fno-elide-constructors
Opção no GCC para desativar esse recurso.
Eu acredito que é chamado Otimização do valor de retorno.
Eu presumo quando f()
retorna C
Objeto O objeto é alocado no espaço da pilha do método de chamada, portanto, nenhuma cópia é necessária para inicializar C a
. Isto é seu default C called
.
C b = a
Isso causa um construtor de cópia, daí o seu CC called
.
BTW, o exemplo do Wiki se parece semelhante ao seu código.