2012-06-24 2 views
26

OK, variables membres can be used pour initialiser d'autres variables membres dans une liste d'initialisation (en prenant soin de l'ordre d'initialisation, etc.). Qu'en est-il des fonctions membres? Pour être précis, cet extrait est-il légal selon la norme C++?Les fonctions membres peuvent-elles être utilisées pour initialiser les variables membres dans une liste d'initialisation?

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 question est bonne, mais l'exemple de code est quelque peu artificielle. Qu'est-ce qui vous empêche de déclarer 'fill_arr' comme étant' static' et ne fait aucun doute que c'est légal? –

+0

Serait-ce thread-safe? Je veux dire, il y a un vecteur local pour 'fill_arr', si c'est static, dois-je le protéger par une sorte de mutex? –

+2

Le 'std :: vector arr' a _automatic storage_, donc il y aurait une instance pour chaque invocation de la fonction' fill_arr'. C'est basique _C++ _... –

Répondre

30

Oui, votre utilisation de la fonction membre dans la liste d'initialisation est valide et conforme à la norme.

Les membres de données sont initialisés dans l'ordre de leur déclaration (et c'est la raison pour laquelle ils doivent apparaître dans la liste d'initialisation dans l'ordre de leur déclaration - la règle que vous avez suivie dans votre exemple). N_ est initialisé en premier et vous pourriez avoir transmis ce membre de données à fill_arr. fill_arr est appelée avant le constructeur, mais comme cette fonction n'accède pas aux membres de données non initialisés (elle n'accède pas du tout aux membres de données), son appel est considéré comme sûr.

Voici quelques excepts pertinentes de la dernière version (N3242 = 11-0012) de la norme du C:

§ 12.6.2.13: Les fonctions membres (y compris les fonctions de membres virtuels, 10.3) peuvent être appelées (...) Cependant, si ces opérations sont effectuées dans un ctor-initializer (ou dans une fonction appelée directement ou indirectement à partir d'un ctor-initialiseur) avant que tous les initialiseurs aient terminé, le résultat de l'opération est indéfini. Exemple:

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: Pour un objet avec un constructeur non triviale, en se référant à tout membre non-statique ou la classe de base de l'objet avant que le constructeur commence résultats d'exécution dans comportement indéfini. Exemple

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

Alors que les objets d'initialisation de la liste d'initialisation, l'objet ne sont pas encore entièrement construits.
Si ces fonctions tentent d'accéder à la partie de l'objet qui n'est pas encore construite, alors c'est un comportement indéfini sinon c'est bien.
voir this answer.

+0

Voilà exactement la question: quelles sont les règles pour l'ordre de construction des fonctions membres? –

+0

@Zhenya voir ceci :: http://stackoverflow.com/a/3899583/981787 – Eight

+0

Corrigez-moi si je me trompe: la question dont vous parlez traite des variables membres plutôt que des fonctions membres. Impliquez-vous que les fonctions membres suivent les mêmes règles? Pour un, gcc 4.4.3 ne se plaint pas si je change l'ordre des déclarations de 'arr_' ​​et' fill_arr() ', alors qu'il émet des avertissements si l'ordre dans la liste d'init n'est pas le même que l'ordre des déclarations . –

Questions connexes