2012-02-15 19 views
5

Al fine di arginare l'argomento in corso nei commenti di an answer I gave recently, vorrei delle risposte costruttive alle seguenti domande:La durata di un riferimento per quanto riguarda il suo obiettivo

  1. È la vita di un riferimento distinta dall'oggetto a cui si riferisce? È un riferimento semplicemente un alias per il suo target?
  2. Un riferimento può sopravvivere al suo obiettivo in un programma ben formato senza comportare un comportamento indefinito?
  3. È possibile fare riferimento a un nuovo oggetto se la memoria allocata per l'oggetto originale viene riutilizzata?
  4. Il seguente codice mostra i punti precedenti senza richiamare un comportamento non definito?

codice di esempio da Ben Voigt e semplificato (eseguirlo sul ideone.com):

#include <iostream> 
#include <new> 

struct something 
{ 
    int i; 
}; 

int main(void) 
{ 
    char buffer[sizeof (something) + 40]; 
    something* p = new (buffer) something; 
    p->i = 11; 
    int& outlives = p->i; 
    std::cout << outlives << "\n"; 
    p->~something(); // p->i dies with its parent object 
    new (p) char[40]; // memory is reused, lifetime of *p (and p->i) is so done 
    new (&outlives) int(13); 
    std::cout << outlives << "\n"; // but reference is still alive and well 
            // and useful, because strict aliasing was respected 
} 
+0

Questo è un sacco di domande, ognuna delle quali richiede una serie di citazioni di parole standard per rispondere correttamente (data la natura della domanda, penso che ci si aspetta che le virgolette standard siano risposte appropriate). È/potrebbe/essere più utile se dovessimo concentrarci su uno di essi e, se utile in quel contesto, rispondere solo agli altri ... – PlasmaHH

+0

Sono d'accordo. Per favore, una domanda per domanda. E scoprirai che le sottoquestioni hanno ricevuto risposta prima. –

+0

Inoltre, quell'esempio di codice ha fatto troppo. Fai un piccolo testcase. –

risposta

9

È la vita di un riferimento distinto da l'oggetto si riferisce? È un riferimento semplicemente un alias per il suo target?

Un riferimento ha il suo ciclo di vita:

int x = 0; 
{ 
    int& r = x; 
}  // r dies now 
x = 5; // x is still alive 

A ref-to const inoltre può estendere la durata del suo arbitro:

int foo() { return 0; } 
const int& r = foo(); // note, this is *not* a reference to a local variable 
cout << r;    // valid; the lifetime of the result of foo() is extended 

anche se questo non è senza avvertimenti:

Un riferimento a const estende solo la durata della vita o f un oggetto temporaneo se il riferimento è a) local e b) legato ad un valore nominale la cui valutazione crea detto oggetto temporaneo. (Quindi non funziona per i membri, o riferimenti locali che sono associati a xvalue.) Inoltre, i riferimenti di valore non costante prolungano la durata nello stesso modo. [@FredOverflow]


Può un riferimento sopravvivere il suo obiettivo in un programma ben formato, senza con conseguente comportamento indefinito?

Certo, finché non lo si usa.


Può un riferimento essere ricollegato a un nuovo oggetto se la memoria allocata per l'oggetto originale viene riutilizzato?

Sì, in alcune condizioni:

[C++11: 3.8/7]: Se, dopo il ciclo di vita di un oggetto è finita e prima della memorizzazione che l'oggetto occupata viene riutilizzato o rilasciato, un nuovo oggetto viene creato al livello di storage posizione che l'oggetto originale occupava, un puntatore che puntava sull'oggetto originale, un riferimento che si riferiva all'oggetto originale, oppure il nome dell'oggetto originale farà automaticamente riferimento al nuovo oggetto e, una volta che la durata del nuovo oggetto è avviato, può essere utilizzato per manipolare il nuovo oggetto, se:

  • l'archiviazione per il nuovo oggetto sovrappone esattamente la posizione di memoria che l'oggetto originale occupato, e
  • il nuovo oggetto è dello stesso tipo dell'oggetto originale (ignorando i primo livello CV-qualificazioni), e
  • il tipo dell'oggetto originale non è const-qualificato e, se un tipo di classe, non contiene alcun membro dati non statico il cui tipo è const-qualificato o un tipo di riferimento e
  • l'oggetto originale era un la maggior parte dell'oggetto derivato (1.8) di tipo T e il nuovo oggetto è un oggetto di derivazione più di tipo T (ovvero non sono sottooggetti di classe base).

Vuol il seguente codice dimostrano i punti di cui sopra senza invocare un comportamento indefinito?

Tl; dr.

+0

Un riferimento a const estende solo la durata di un oggetto temporaneo se il riferimento è a) local e b) associato a un valore di prova la cui valutazione crea detto oggetto temporaneo. (Quindi non funziona per i membri, o riferimenti locali che sono associati a xvalue.) Inoltre, i riferimenti di valore non costante prolungano la durata nello stesso modo. – fredoverflow

+0

@FredOverflow: Ta! –

5
  1. Sì. Ad esempio, i riferimenti non statici locali hanno durata di archiviazione automatica e tempo di lievitazione corrispondente e possono riferirsi a oggetti con una durata maggiore.

  2. Sì, i riferimenti pendenti sono un esempio. Finché tali riferimenti non vengono usati in nessuna espressione quando diventano penzoloni, stanno bene.

  3. C'è una regola speciale nella clausola 3 su questo caso. Nomi di oggetti, puntatori e riferimenti si riferiscono automaticamente al nuovo oggetto che riutilizza la memoria in condizioni ristrette. Credo che sia alla fine del 3.8. Qualcuno che ha le specifiche a portata di mano si prega di compilare il riferimento corretto qui.