2012-06-24 6 views
26

OK, variabili membro can be used per inizializzare le altre variabili membro in un elenco di inizializzazione (con attenzione all'ordine di inizializzazione, ecc.). E riguardo le funzioni dei membri? Per essere precisi, questo snippet è legale secondo lo standard C++?possono essere utilizzate per inizializzare le variabili membro in un elenco di inizializzazione?

struct foo{ 
    foo(const size_t N) : N_(N), arr_(fill_arr(N)) { 
    //arr_ = fill_arr(N); // or should I fall back to this one? 
    } 

    std::vector<double> fill_arr(const size_t N){ 
    std::vector<double> arr(N); 
    // fill in the vector somehow 
    return arr; 
    } 

    size_t N_; 
    std::vector<double> arr_; 
    // other stuff 
}; 
+0

La domanda è buona, ma il codice di esempio è un po 'artificiale. Cosa ti impedisce di dichiarare 'fill_arr' come' static' e non hai dubbi che sia legale? –

+0

Sarebbe thread-safe? Voglio dire, c'è un vettore locale in 'fill_arr', se questo è' statico', devo proteggerlo con una sorta di mutex? –

+2

'std :: vector arr' ha _automatic storage_, quindi ci sarebbe un'istanza di esso per ogni invocazione della funzione' fill_arr'. È semplice _C++ _... –

risposta

30

Sì, l'utilizzo della funzione membro nell'elenco di inizializzazione è valido e conforme allo standard.

I membri di dati vengono inizializzati nell'ordine della loro dichiarazione (e questo è il motivo per cui dovrebbero apparire nell'elenco di inizializzazione nell'ordine della loro dichiarazione - la regola che hai seguito nell'esempio). N_ viene inizializzato per primo e potresti aver passato questo membro dati a fill_arr. fill_arr viene chiamato prima del costruttore ma poiché questa funzione non accede ai membri dati non inizializzati (non accede affatto ai membri dati) la sua chiamata è considerata sicura.

Ecco alcuni stralci rilevanti l'ultima bozza (N3242 = 11-0012) del C++ standard di:

§ 12.6.2.13: funzioni membri (comprese le funzioni membro virtuali, 10.3) può essere chiamato (...) Tuttavia, se queste operazioni vengono eseguite in un iniziatore di ctor (o in una funzione chiamata direttamente o indirettamente da un iniziatore di ctor) prima che tutti gli inizializzatori di mem per le classi di base abbiano completato, il risultato dell'operazione non è definito. Esempio:

class A { public: A(int); }; 

class B : public A { 
    int j; 
public: 
    int f(); 
    B() : A(f()), // undefined: calls member function 
       // but base A not yet initialized 
    j(f()) { } // well-defined: bases are all initialized 
}; 

class C { 
public: 
    C(int); 
}; 

class D : public B, C { 
    int i; 
public: 
    D() : C(f()), // undefined: calls member function 
       // but base C not yet initialized 
    i(f()) { } // well-defined: bases are all initialized 
}; 

§12.7.1: Per un oggetto con un costruttore non banale, riferendosi a qualsiasi classe utente o base non statici dell'oggetto prima del costruttore comincia risultati di esecuzione in comportamento indefinito. Esempio

struct W { int j; }; 
struct X : public virtual W { }; 
struct Y { 
    int *p; 
    X x; 
    Y() : p(&x.j) { // undefined, x is not yet constructed 
    } 
}; 
3

Mentre oggetti inizializzazione nell'elenco di inizializzazione, l'oggetto non è ancora completamente costruito.
Se quelle funzioni cercano di accedere alla parte dell'oggetto che non è ancora stata costruita, allora si tratta di un comportamento non definito, altrimenti va bene.
vedere this answer.

+0

Questa è esattamente la sostanza della domanda: quali sono le regole per l'ordine di costruzione delle funzioni membro? –

+0

@Zhenya vedere questo :: http://stackoverflow.com/a/3899583/981787 – Eight

+0

Correggimi se ho torto: la domanda a cui ti riferisci riguarda le variabili membro invece delle funzioni membro. Sottintendi che le funzioni dei membri seguono le stesse regole? Per uno, gcc 4.4.3 non si lamenta se cambio l'ordine delle dichiarazioni di 'arr_' ​​e' fill_arr() ', mentre emette avvisi se l'ordine nella lista di init non è lo stesso dell'ordine delle dichiarazioni . –