0

我想知道以下两个班级有什么区别。

示例 1:

class A
{
string name;
public:
  A(const char* _name):name(_name){}
  void print(){cout<<"A's name:"<<name<<endl;}
};

示例 2:

class A
{
string name;
public:
  A(const char* _name){name(_name);}
  void print(){cout<<"A's name:"<<name<<endl;}}

为什么示例1通过而最后一个是错误的?谢谢

4

6 回答 6

3

第一个例子是一个实际的初始化。它有许多优点,包括作为设置const成员的唯一方法,以及具有适当的异常安全性。

第二个示例不是有效的 C++,AFAIK。如果你写的是name = name_,那么这只是正常的分配。当然,这并不总是可能的。该对象可能是const,也可能没有定义赋值运算符。这种方法也可能不如第一个示例有效,因为该对象既是默认初始化的是分配的。

至于为什么初始化列表在构造函数体之前;好吧,这就是语言的定义方式。

于 2011-05-02T11:16:42.673 回答
3

在示例 1 中,您立即使用给定值初始化字符串。在示例 2 中,您首先创建一个空字符串,然后再分配它。

尽管存在一些性能差异并且忽略了由于复制构造函数处理等可能存在的差异,但它基本上是相同的结果。

但是,一旦您使用const成员,您将不得不使用示例 1 的方式来执行此操作,例如,我通常通过以下方式创建唯一 ID:

class SomeObject
{
    static unsigned int nextID = 0;
    const unsigned int ID;
    SomeObject() : ID(nextID++)
    {
        // you can't change ID here anymore due to it being const
    }
}
于 2011-05-02T11:22:26.960 回答
2

这就是语言的定义方式。成员初始化器应该放在构造函数的主体之前。

于 2011-05-02T11:15:51.873 回答
1

在第一个示例中,成员名称使用 ctr 初始化,并将 char * 作为参数。

在第二种情况下,它首先使用默认 ctr 进行初始化,然后通过赋值运算符 (operator=) 获取值。这就是为什么你的情况是错误的,它已经在那里构造了,所以你不能再次使用 ctr 你可以只使用赋值运算符。

于 2011-05-02T11:17:14.260 回答
0

原因是名称查找在初始化列表和函数体中的工作方式不同:

class A
{
  std::string foo; // member name
public:
  A(const char* foo) // argument name
    : foo(foo) // member foo, followed by argument foo.
  {
    std::cout << foo; // argument foo.
  }
};

foo如果初始化列表在函数体内,则 member和 argument之间会有歧义foo

于 2011-05-02T11:18:51.347 回答
0

初始化列表背后的动机是由于 const 字段按值保存对象(与引用/指针字段相反)。

此类字段必须仅初始化一次(由于它们的常量性)。如果 C++ 没有初始化列表,那么 ctor 看起来像:

class A {
public:
  const string s;
  const string t;

  A() {
    // Access to either s or t is not allowed - they weren't initialized
    s = "some-string";
    // now you can access s but you can't access t
    f(*this);

    t = "some other string";
    // From now you can access both ...
  }
}


void f(A& a) {
  // Can you access a.s or a.t?
  cout << a.s << a.t;
}

如果没有初始化列表,ctor 可以将部分初始化的类型对象传递A给函数,并且该函数将无法知道哪些字段已初始化。编译器/链接器检查的风险太大且非常困难。

于 2011-05-02T11:28:10.137 回答