Question

S'il vous plaît considérez le code suivant,

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

Sortie sur MSVC

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

Sortie de GCC

Constructing!
before return
Destructing..

Le résultat qui vient sur MSVC semble incorrecte.

Questions

  1. AFAIK, GCC produit le résultat correct ici. Pourquoi MSVC donne des résultats différents et pourquoi il fait la construction de copie?
  2. const foo& f = get() et const foo f = get() produit même sortie en raison de l'optimisation de la valeur de retour. Dans ce cas, de quelle manière l'écriture doit être préférée?

Toutes les pensées ..

Était-ce utile?

La solution

Votre build MSVC n'a pas optimisations sur. les activer, vous obtenez une sortie identique pour les deux.

GCC est qu'exécuter, par défaut, sur votre RVO temporaire. Il est fait essentiellement:

const foo& f = foo();

MSVC n'est pas. Cela rend la foo dans la fonction, la copie à l'extérieur de la fonction (ergo l'appel constructeur de copie), détruisant la foo intérieure, se lie alors la référence.

Les deux sorties sont correctes. RVO est une instance où la norme permet explicitement le comportement observable du programme pour changer.

Autres conseils

Vous voyez les optimisation de la valeur de retour , qui est une sorte de copie élision . Les deux programmes sont corrects; le compilateur est en particulier compte tenu de la possibilité d'éliminer un temporaire qui ne sert qu'à déplacer des données d'un objet permanent à un autre.

La fonction get () est la construction du local (impression Constructing!), Et le retour d'un objet Foo en valeur. L'objet Foo retourné doit être créé et se fait donc par la construction de copie (Copie d'impression CONSTRUIRE!). Notez que ceci est la valeur de l'objet attribué à la const foo & f dans le principal.

Avant cette affectation se déroule bien, la fonction doit revenir de get () et les variables locales (c.-à-foo f, en get ()) doivent être détruits. (Imprimer 1er Destructing ..) A partir de là le programme se termine (à savoir les déclarations du principal) alors l'objet retourné par get () et attribué à « f » est détruit. (Imprimer 2 Destructing ...)

La raison pour laquelle vous voyez une sortie différente pour les deux compilateurs est que GCC optimise la valeur de retour pour get () et remplace simplement const foo &f = get() à const foo &f = foo;

1) Cela se produit en raison de différentes stratégies d'optimisation. Parce que vous n'avez pas = opérateur, MSVC peut restructurer le code à quelque chose comme const foo & f (get ()) donc exécuter onstructor copie. 2) En fonction de ce que vous voulez acheive:

const foo& f = get();
f = get(); // Incorrect, const references cannot be reassigned.
const foo g = get();
g = get(); // Correct.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top