kunnen lidfuncties worden gebruikt om lidvariabelen in een initialisatielijst te initialiseren?

OK, lidvariabelen kan zijn gebruikt om andere ledvariabelen in een initialisatielijst te initialiseren (met zorg voor de initialisatiebestelling, enz.). Hoe zit het met ledenfuncties? Om specifiek te zijn, is dit fragment wettelijk volgens de C ++ -standaard?

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 fill_arr(const size_t N){
    std::vector arr(N);
   //fill in the vector somehow
    return arr;
  }

  size_t N_;
  std::vector arr_;
 //other stuff
};
27
De vraag is goed, maar het codevoorbeeld is enigszins kunstmatig. Wat voorkomt dat u fill_arr als statisch declareert en twijfelt er niet aan dat het legaal is?
toegevoegd de auteur K-ballo, de bron
De std :: vector arr heeft automatische opslag , dus er zou een instantie van zijn voor elke aanroep van de functie fill_arr . Dat is standaard C ++ ...
toegevoegd de auteur K-ballo, de bron
Zou dat thread-safe zijn? Ik bedoel, er is een lokale vector voor fill_arr , als dat statisch is, moet ik het dan beschermen met een soort mutex?
toegevoegd de auteur ev-br, de bron

2 antwoord

Ja, uw gebruik van de ledenfunctie in de initialisatielijst is geldig en voldoet aan de norm.

Gegevensleden worden geïnitialiseerd in de volgorde van hun aangifte (en dat is de reden waarom ze in de initialisatielijst moeten verschijnen in de volgorde van hun aangifte - de regel die u in uw voorbeeld hebt gevolgd). N _ wordt als eerste geïnitialiseerd en u zou dit gegeven kunnen doorgeven aan fill_arr . fill_arr wordt aangeroepen voor de constructor, maar omdat deze functie geen toegang tot niet-geïnitialiseerde gegevens-leden heeft (het heeft helemaal geen toegang tot gegevens), wordt zijn oproep als veilig beschouwd.

Hier zijn enkele relevante uitzonderingen van de nieuwste versie (N3242 = 11-0012) van de C ++ -standaard:

§ 12.6.2.13: Ledenfuncties (inclusief virtuele lidfuncties,   10.3) kan worden opgeroepen voor een object in aanbouw. ​​(...) Als deze bewerkingen echter worden uitgevoerd in een ctor-initializer (of in een functie   direct of indirect aangeroepen door een ctor-initializer) vóór alle   mem-initializers voor basisklassen zijn voltooid, het resultaat van de   bewerking is niet gedefinieerd. Bijvoorbeeld:

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: Voor een object met een niet-triviale constructor, verwijzend naar   elke niet-statische lid- of basisklasse van het object vóór de   constructor start uitvoeringsresultaten in ongedefinieerd gedrag. Voorbeeld

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
   }
};
31
toegevoegd

While initializing objects in the initialization list, the object is not yet fully constructed.
If those function tries to access the part of the object which is not yet constructed then that is a undefined behavior else its fine.
see this answer.

3
toegevoegd
Dat is precies het vlees van de vraag: wat zijn de regels voor de constructievolgorde voor de lidfuncties?
toegevoegd de auteur ev-br, de bron
Corrigeer me als ik het mis heb: de vraag waar je het over hebt, behandelt lidvariabelen in plaats van lidfuncties. Houdt u in dat ledenfuncties dezelfde regels volgen? Ten eerste klaagt gcc 4.4.3 niet als ik de volgorde van declaraties van arr _ en fill_arr() wijzig, terwijl het wel waarschuwingen geeft als de volgorde in de initiële lijst is niet hetzelfde als de volgorde van declaraties.
toegevoegd de auteur ev-br, de bron
Nou, daar is ook zijn commentaar op zijn antwoord ... (+1 voor de link toch.)
toegevoegd de auteur ev-br, de bron
toegevoegd de auteur Eight, de bron
@Zhenya 1e deel van het antwoord van sbi ( stackoverflow.com/a/3899583/981787 ) is voor ledenfuncties.
toegevoegd de auteur Eight, de bron