初始化列表,局部变量与数据成员

时间:2012-10-09 05:08:17

标签: c++ oop constructor initialization

#include <iostream>
using namespace std;
class Ex {
private:
    int i;
    float f;
public:
    Ex(int i,float f):i(i),f(f) {
        cout << this->i << '\t' << this->f << endl;
    }
    ~Ex(){
        cout << "destructor";
    }
};
int main() {
    Ex i(10,20.1f);
}

在我上面编写的程序中,如果构造函数是参数化构造函数,如下所示:

Ex(int i,float f){
        i=i;
        f=f;
        cout << this->i << '\t' << this->f << endl;
    }

这里对象的数据成员被初始化为垃圾,因为数据成员由于同名的局部变量而被隐藏。 但是在上面的程序中,如果没有明确的话,它可以正常工作。怎么样?

3 个答案:

答案 0 :(得分:2)

以前曾提出过类似的问题,例如: herehere,但许多答案指出这是(与Konstantin D - Infragistics所说的相反)不是特定于编译器的,我找不到任何实际引用相关部分的答案。标准。

所以他们在这里。我更加强调突出主要陈述。

  

(§12.6.2/ 10)在非委托构造函数中,初始化按以下顺序进行:

     

- 首先,仅对于派生程度最高的类(1.8)的构造函数,虚拟基类按照它们出现在基类的有向非循环图的深度优先从左到右遍历的顺序进行初始化,其中“从左到右”是派生类base-specifier-list中基类出现的顺序    - 然后,直接基类按声明顺序初始化,因为它们出现在base-specifier-list中(无论mem-initializers的顺序如何)。
   - 然后,非静态数据成员按照在类定义中声明的顺序进行初始化(再次与mem-initializers的顺序无关)。
   - 最后,执行构造函数体的复合语句。

     

(§12.6.2/ 12)mem-initializer的表达式列表或braced-init-list中的名称在构造函数的范围内进行评估,其中mem-initializer是指定。 [例如:

    class X {
      int a;
      int b;
      int i;
      int j;
    public:
      const int& r;
      X(int i): r(a), b(i), i(i), j(this->i) { }
    };
     

初始化X::r以引用X::a,使用构造函数参数X::b的值初始化i使用值{}初始化X::i构造函数参数i ,并使用X::j的值初始化X::i;每次创建类X的对象时都会发生这种情况。 - 结束例子]
  [注意:因为mem-initializer是在构造函数的范围内计算的,所以this指针可以在mem-initializer的表达式列表中用于引用正在初始化的对象。 - 结束说明]

答案 1 :(得分:1)

由于以下几点,所有C ++编译器都遵循规则:

  1. 构造函数初始值设定项列表只能与类构造函数一起存在
  2. 在初始化列表中,只有相同的类成员和基类 构造函数可以被称为
  3. 初始化的顺序与类数据成员的顺序相同 宣布
  4. 当编译器将if视为初始化列表的一部分时,它会立即识别为类成员,并且一切正常(第2点)。
    如果您尝试除if以外的任何其他操作,编译器将给出错误。

    在第二种情况下,您进行了分配,编译器有if的2个候选者。它可以是类成员或局部变量。由于局部变量位于最大范围内,因此编译器将i视为i而不是this->i

答案 2 :(得分:0)

编译器旨在使用左侧if作为类范围的成员,右侧if作为成员构造函数范围。