2015-11-23 15 views
6

DatoQualche compilatore potrà mai elidere queste copie?

struct Range{ 
    Range(double from, double to) : from(from), to(to) {} 
    double from; 
    double to; 
    // if it matters to the compiler, we can add more fields here to make copying expensive 
}; 

struct Box{ 
    Box(Range x, Range y) : x(x), y(y) {} 
    Range x; 
    Range y; 
}; 

someone said che nel Box box(Range(0.0,1.0),Range(0.0,2.0)), il compilatore può evitare di copiare Range oggetti complessivamente da costruirli all'interno box per cominciare.

Qualche compilatore esegue effettivamente questo?

I miei tentativi non sono riusciti.

+1

Se il compilatore è in discesa, assicurati. Li eliderà. – 101010

+1

@ 101010 Qualcuno particolare compilatore moderno è decente? Non posso farlo accadere. – Museful

+1

Dovresti commentare questa risposta senza fare una domanda doppia. – LogicStuff

risposta

8

Il compilatore può - e normalmente lo fa - elide le copie dall'elemento temporaneo all'argomento. Il compilatore non può elidere la copia dall'argomento ai membri. Sebbene sia tecnicamente possibile elidere queste copie in alcuni casi, non viene fornita l'autorizzazione pertinente. La sezione del standard è 12,8 [class.copy] paragrafo 31 che enuncia 4 situazioni in cui una copia può essere eliso (le regole esatte sono un po 'non banale):

  1. Quando si restituisce un nome, funzione locale variabile usando il suo nome.
  2. Quando si utilizza una variabile locale denominata, funzione in un'espressione throw.
  3. Quando si copia un oggetto temporaneo.
  4. Quando si rileva un'eccezione in base al valore.

Passare un argomento con nome come parametro alla costruzione di una variabile membro è, chiaramente, nessuna di queste situazioni.

Lo sfondo essenziale delle regole per la copia elisione è che in alcuni contesti la dichiarazione delle funzioni è sufficiente per determinare quando verrà utilizzato un oggetto. Se è chiaro nel momento della costruzione in cui l'oggetto può essere costruito, può essere eluito. Il chiamante di un costruttore non può determinare in base solo alla dichiarazione del costruttore in cui verrà utilizzato l'oggetto.

+0

Come complemento alla risposta (molto buona) di cui sopra, vorrei aggiungere che un modo per mantenere il controllo è usare (forse const) argomenti di riferimento o puntatori e copiare solo quando è veramente necessario. In questo modo, sai esattamente cosa succede e non vengono fatte copie inutili, e sei sostanzialmente indipendente da ciò che lo scrittore di compilatori ha fatto in termini di ottimizzazioni. Inoltre, non è necessario provare a decifrare i documenti standard difficili da leggere. –

+0

@ ErikAlapää che utilizza i riferimenti const interferisce con la semantica del movimento; Direi che è meglio passare di valore qui. In questo specifico codice, possiamo sostituire 'x (x)' da 'x (std :: move (x))' ecc. Risultando in (per ciascun parametro) 2 mosse di cui 1 può essere eli- minato; ma se si cambiano i riferimenti const, c'è una copia che non può essere elidata. –

+0

@MM Interessante - Sto iniziando a capire i refval e lo std :: move, ma tendo ad usare metodi collaudati di vecchio stile;) Ma comunque, se uso un puntatore, posso assicurarmi di minimizzare la copia, poiché Devo esplicitamente copiare per ottenere una copia. –

0

Quel Qualcuno sono io. Quindi permettimi di cancellare la mia posizione.

Non ho mai detto che nel Box box(Range(0.0,1.0),Range(0.0,2.0)), il compilatore può evitare di copiare oggetti Gamma del tutto da loro costruendo all'interno della scatola per cominciare. Quello che ho detto è stata:

Sì certo che può, in particolare questo tipo di contesto copia elisione cade sotto il criterio di copia elision specificato nella 12.8/p31.3 copiare e spostare oggetti di classe [class.copy] dello standard:

(31,3) - quando un oggetto classe temporanea che non è stato legato ad un riferimento (12.2) verrebbe copiato/spostato in un oggetto di classe con lo stesso tipo (ignorando cv-qualificazione), la l'operazione di copia/spostamento può essere omessa dallo che costruisce l'oggetto temporaneo direttamente nella destinazione della copia/spostamento omessa .

Il Sì certo che può, parte vale per gli oggetti temporanei passati nel costruttore (che può essere Elide secondo la norma come detto sopra).Non ho mai detto che i parametri possono essere eliminati fino all'elenco di inizializzazione del costruttore Box.

Dopotutto, questo caso non si qualifica per nessuno dei criteri in cui copia elisione può essere applicata come standard.

Ho anche detto che anche se un determinato contesto è qualificato come contesto in cui è possibile applicare copy elision, il compilatore non è obbligato a seguire. Se ti affidi a quegli effetti allora il tuo programma non è considerato portatile.