【问题标题】:can member functions be used to initialize member variables in an initialization list?可以使用成员函数来初始化初始化列表中的成员变量吗?
【发布时间】:2012-06-24 00:40:30
【问题描述】:

好的,成员变量can be used 用于初始化初始化列表中的其他成员变量(注意初始化顺序等)。成员函数呢?具体来说,根据 C++ 标准,这个 sn-p 合法吗?

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

【问题讨论】:

  • 问题很好,但是代码示例有些人为。是什么阻止您将 fill_arr 声明为 static 并且毫无疑问它是合法的?
  • 那是线程安全的吗?我的意思是,fill_arr 有一个本地向量,如果那是static,我是不是用某种互斥锁来保护它?
  • std::vector&lt;double&gt; arr 具有自动存储,因此每次调用函数fill_arr 都会有一个实例。这是基本的C++...
  • 本例中最好将fill_arr标记为const。为了可读性。

标签: c++ initialization-list


【解决方案1】:

是的,您在初始化列表中使用的成员函数是有效的并且符合标准。

数据成员按照它们的声明顺序进行初始化(这就是为什么它们应该按照声明的顺序出现在初始化列表中的原因 - 您在示例中遵循的规则)。 N_ 首先初始化,您可以将此数据成员传递给fill_arrfill_arr 在构造函数之前被调用,但是因为这个函数不访问未初始化的数据成员(它根本不访问数据成员),所以它的调用被认为是安全的。

以下是 C++ 标准最新草案 (N3242=11-0012) 中的一些相关例外:

§ 12.6.2.13:成员函数(包括虚成员函数, 10.3) 可以为正在构造的对象调用。(...) 但是,如果这些操作是在 ctor-initializer(或函数中)执行的 在所有 基类的 mem-initializers 已经完成,结果 操作未定义。示例:

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:对于具有非平凡构造函数的对象,参考 对象之前的任何非静态成员或基类 构造函数开始执行导致未定义的行为。示例

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

【讨论】:

    【解决方案2】:

    在初始化列表中初始化对象时,该对象尚未完全构造。
    如果这些函数试图访问尚未构造的对象部分,那么这是一个未定义的行为,否则它很好。
    this answer

    【讨论】:

    • 这正是问题的核心:成员函数的构造顺序的规则是什么?
    • 如果我错了,请纠正我:您所指的问题涉及成员变量而不是成员函数。您是否暗示成员函数遵循相同的规则?一方面,如果我切换 arr_fill_arr() 的声明顺序,gcc 4.4.3 不会抱怨,而如果 init-list 中的顺序与声明的顺序不同,它会发出警告。
    • @Zhenya sbi 回答的第一部分 (stackoverflow.com/a/3899583/981787) 是针对成员函数的。
    • 嗯,他的回答也有他的评论......(无论如何,+1 链接。)
    猜你喜欢
    • 2019-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-14
    • 1970-01-01
    相关资源
    最近更新 更多