2015-10-12 16 views
14

Nel seguente codice, sono pS e s.pS garantiti per essere uguali nella riga finale? In altre parole, nella dichiarazione S s = S();, posso essere sicuro che un S temporaneo non verrà costruito?In S s = S() è garantito che non verrà creato alcun temporaneo?

#include <iostream> 
using namespace std; 

struct S 
{ 
    S() { pS = this; } 
    S* pS; 
}; 

int main() 
{ 
    S s = S(); 
    S* pS = &s; 
    cout << pS << " " << s.pS << endl; 
} 

In ogni compilatore Ho provato questo in pS == s.pS, ma non sono sufficientemente familiarità con lo standard per essere in grado di soddisfare me stesso che questo è garantito.

+2

No - è un temporaneo che potrebbe essere ottimizzato –

+0

In base alle mie conoscenze, si può presumere che sarà RVO e ci si deve preoccupare solo se si verificano circostanze speciali che richiedono un trattamento speciale o garanzie di prestazioni. Altrimenti, questo è praticamente garantito e dovrebbe essere usato. – Mordachai

+2

@Mordachai Questo non ha nulla a che fare con RVO. La R sta per ritorno. Non c'è ritorno qui. – Barry

risposta

16

NO

Il compilatore non è obbligata fare copia elision. Lo standard specifica semplicemente che, [class.copy]:

Quando determinati criteri sono soddisfatti, un'implementazione è consentito omettere la copia costruzione/spostamento di un oggetto classe [...]

Posso disabilitare la copia elisione tramite -fno-elide-constructors, e quindi i due puntatori saranno sicuramente diversi. Per esempio:

$g++ -std=c++11 -Wall -pedantic -fno-elide-constructors -Wall -Wextra main.cpp && ./a.out 
0x7fff5a598920 0x7fff5a598930 

E nel caso generale, se aggiungiamo S(S&&) = delete, quindi il codice di cui sopra non sarebbe nemmeno la compilazione.

+0

Ho pensato che C++ 11 o 13 lo rendesse obbligatorio. E anche così - credo che sia nella categoria delle "virtualmente garantite" e delle "migliori pratiche" di non preoccuparsi più di questo (con il normale avvertimento di: se fai test delle prestazioni, e scopri che questo è un problema reale è un percorso di hot code, quindi e solo allora ti coinvolgerebbe manualmente nell'ottimizzarlo manualmente) ... – Mordachai

+0

@Mordachai Nope. La frase che ho citato proviene da N4527. – Barry

+2

@Mordachai Non è assolutamente "la migliore pratica" non preoccuparsi di questo! – Pixelchemist

11

La maggior parte dei compilatori esegue ciò che viene chiamato copy/move elision, che è specificato dallo standard C++. Ma non è garantito. Ad esempio, puoi compilare con -fno-elide-constructors in gcc e vedrai tutti i costruttori in tutta la loro gloria.

Live example on Coliru

5

Non vi è alcuna garanzia che non ci sarà temporaneo. Ma i compilatori Big Three lo ottimizzeranno (anche con lo switch -O0).

per garantire, temporanea a tutti solo scrivere:

int main() 
{ 
    // ... 
    S s{}; 
    // ... 
} 

O semplicemente S s;.