Pergunta

Por favor, considere o seguinte código,

struct foo
{
    foo()
    {
        std::cout << "Constructing!" << std::endl;
    }

    foo(const foo& f)
    {
        std::cout << "Copy constructing!" << std::endl;
    }

    ~foo()
    {
        std::cout << "Destructing.." << std::endl;
    }
};

foo get()
{
    foo f;
    return f;
}

int main()
{
    const foo& f = get();
    std::cout << "before return" << std::endl;
    return 0;
}

Saída em MSVC

Constructing!
Copy constructing!
Destructing..
before return
Destructing..

Saída do GCC

Constructing!
before return
Destructing..

O resultado que vem no MSVC parece incorreto.

Questões

  1. AFAIK, GCC produz o resultado correto aqui.Por que o MSVC está dando resultados diferentes e por que está fazendo a construção de cópias?
  2. const foo& f = get() e const foo f = get() produz a mesma saída devido à otimização do valor de retorno.Nesse caso, qual forma de escrita deve ser preferida?

Alguma ideia..

Foi útil?

Solução

Sua compilação MSVC não tem otimizações. Ligue -os, você receberá uma saída idêntica para ambos.

O GCC está apenas executando, por padrão, RVO no seu temporário. Está basicamente fazendo:

const foo& f = foo();

MSVC não é. Está fazendo o foo Na função, copiando-a para a função externa (ergo a chamada de cópia-construtor), destruindo o interior foo, então liga a referência.

Ambas as saídas estão corretas. O RVO é uma instância em que o padrão permite explicitamente o comportamento observável do programa.

Outras dicas

Você está vendo o Otimização do valor de retorno, que é um tipo de Copie a elisão. Ambos os programas estão corretos; O compilador recebe especificamente a opção de eliminar um temporário que serve apenas para mover dados de um objeto permanente para outro.

A função get() está construindo o local (print Construindo!) E retornando um objeto Foo por valor.O objeto Foo que está sendo retornado deve ser criado e isso é feito por meio da construção de cópia (construção de cópia de impressão!).Observe que este é o valor do objeto atribuído a const foo & f em main.

Antes que essa atribuição ocorra, a função deve retornar de get() e de variáveis ​​locais (ou seja,foo f;em get()) deve ser destruído.(print 1st Destructing..) A partir daí o programa termina (ou seja,retorna de main), então o objeto retornado por get() e atribuído a "f" é destruído.(imprimir 2ª Destruição...)

A razão pela qual você está vendo resultados diferentes para os dois compiladores é que o GCC está otimizando o valor de retorno de get() e simplesmente substituindo const foo &f = get() para const foo &f = foo;

1) Isso acontece devido a diferentes estratégias de otimização. Como você não possui operador =, o MSVC pode reestruturar o código em algo como const foo & f (get ()) executando, portanto, cópia onStructor. 2) Depende do que você deseja acertar:

const foo& f = get();
f = get(); // Incorrect, const references cannot be reassigned.
const foo g = get();
g = get(); // Correct.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top