Domanda

Si prega di considerare il seguente codice,

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

Output MSVC

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

Output di GCC

Constructing!
before return
Destructing..

Il risultato che si accende MSVC sembra corretto.

Domande

  1. per quanto ne so, GCC produce il risultato corretto qui. Perché MSVC sta dando risultati diversi e perché sta facendo copia costruzione?
  2. const foo& f = get() e const foo f = get() produce stesso output a causa di ottimizzazione del valore di ritorno. In questo caso, quale modo di scrivere dovrebbe essere preferito?

Ogni pensiero ..

È stato utile?

Soluzione

La build MSVC non ha ottimizzazioni su. accenderli, si otterrà un output identico per entrambi.

GCC è semplicemente eseguendo, per impostazione predefinita, RVO sul temporanea. E 'fondamentalmente facendo:

const foo& f = foo();

MSVC non lo è. Sta facendo il foo nella funzione, la copia al di fuori della funzione (ergo la chiamata costruttore di copia), distruggendo il foo interna, poi si lega il riferimento.

Entrambe le uscite siano corrette. RVO è un caso in cui la norma consente esplicitamente il comportamento osservabile del programma per cambiare.

Altri suggerimenti

Stai visualizzando il valore di ritorno di ottimizzazione , che è una sorta di copia elision . Entrambi i programmi sono corrette; il compilatore specificamente è data la possibilità di eliminare un temporaneo che serve solo per spostare dati da un oggetto fisso ad un altro.

La funzione get () sta costruendo il locale (la costruzione di stampa!), E restituendo un oggetto Foo per valore. L'oggetto Foo essere restituito deve essere creato e viene fatto in modo tramite copia costruzione (stampa copia costruzione!). Si noti che questo è il valore oggetto assegnato alla const foo & F nella principale.

Prima che l'assegnazione avviene però, la funzione deve restituire da get () e variabili locali (cioè foo F; a get ()) deve essere distrutto. (Stampa prima Distruzione ..) Da lì i termina di programma (cioè ritorna dalla principale) allora l'oggetto restituito da get () e assegnato a "f" viene distrutto. (Stampa secondo Distruzione ...)

Il motivo che state vedendo output diverso per i due compilatori GCC è che sta ottimizzando il valore restituito per get () ed è semplicemente sostituendo const foo &f = get() a const foo &f = foo;

1) Questo accade a causa della diversa strategia di ottimizzazione. Perché non si dispone di operatore =, MSVC codice può ristrutturare a qualcosa come foo const & f (get ()) quindi eseguire la copia onstructor. 2) Dipende da cosa si vuole acheive:

const foo& f = get();
f = get(); // Incorrect, const references cannot be reassigned.
const foo g = get();
g = get(); // Correct.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top