2012-06-24 22 views
26

OK, variables miembro can be used para inicializar otras variables miembro en una lista de inicialización (teniendo cuidado de la orden de inicialización, etc.). ¿Qué hay de las funciones miembro? Para ser específico, ¿este fragmento es legal según el estándar de C++?¿pueden usarse las funciones miembro para inicializar las variables miembro en una lista de inicialización?

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 pregunta es buena, pero el ejemplo de código es un poco artificial. ¿Qué le impide declarar 'fill_arr' como' estático' y no tiene dudas de que es legal? –

+0

¿Sería eso seguro para subprocesos? Quiero decir, hay un vector local para 'fill_arr', si eso es' static', ¿debo protegerlo con una especie de mutex? –

+2

El 'std :: vector arr' tiene _automatic storage_, por lo que habría una instancia para cada invocación de la función' fill_arr'. Eso es básico _C++ _... –

Respuesta

30

Sí, su uso de la función de miembro en la lista de inicialización es válido y cumple con la norma.

Los miembros de datos se inicializan en el orden de su declaración (y esa es la razón por la que deberían aparecer en la lista de inicialización en el orden de su declaración, la regla que siguió en su ejemplo). N_ se inicializa primero y puede haber pasado este miembro de datos al fill_arr. fill_arr se llama antes del constructor pero debido a que esta función no accede a los miembros de datos no inicializados (no tiene acceso a los miembros de datos) su llamada se considera segura.

Éstos son algunos exceptúa relevantes desde el último borrador (N3242 = 11-0012) del C++ estándar:

§ 12.6.2.13: funciones miembros (incluyendo las funciones miembro virtuales, 10.3) se pueden llamar para un objeto en construcción. (...) Sin embargo, si estas operaciones se realizan en un inicializador de ctor (o en una función llamada directa o indirectamente desde un ctor-inicializador) antes de que todos los mem-initializers para clases base tengan completado, el resultado de la operación no está definido. Ejemplo:

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: Para un objeto con un constructor no trivial, en referencia a cualquier miembro o base de clase no estática del objeto antes de la constructor comienza resultados de la ejecución en comportamiento indefinido Ejemplo

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

mientras que los objetos de inicialización de la lista de inicialización, el objeto aún no está totalmente construidos.
Si esa función intenta acceder a la parte del objeto que aún no está construida, entonces ese es un comportamiento indefinido, de lo contrario está bien.
ver this answer.

+0

Esa es exactamente la esencia de la pregunta: ¿cuáles son las reglas para el orden de construcción de las funciones miembro? –

+0

@Zhenya vea esto :: http://stackoverflow.com/a/3899583/981787 – Eight

+0

Corrígeme si me equivoco: la pregunta a la que se refiere trata de las variables miembro en lugar de las funciones miembro. ¿Implica que las funciones de los miembros siguen las mismas reglas? Por un lado, gcc 4.4.3 no se queja si cambio el orden de las declaraciones de 'arr_' ​​y' fill_arr() ', mientras que sí emite advertencias si el orden en la lista de inicio no es el mismo que el orden de las declaraciones . –

Cuestiones relacionadas