2011-05-02 65 views
0

我想知道下面两节课有什么不同。为什么C++初始化列表在大括号之前?

例子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传递,最后一个是错误的? 谢谢

回答

2

这就是语言的定义。成员初始值设定项应放置在构造函数的主体之前。

3

第一个示例是实际的初始化。它具有许多优点,包括成为const成员的唯一方式,并具有适当的异常安全性。

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

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

1

在第一个示例中,成员名称使用获取char *作为参数的ctr进行初始化。

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

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和论证foo之间的歧义。

+0

感谢所有的答案,我已经知道了,它是在调用构造函数之前构造的,所以不能再次初始化,所以必须赋值。谢谢 – John 2011-05-04 02:02:31

3

在示例1中,您马上用给定值初始化字符串。 在示例2中,首先创建一个空字符串并稍后分配它。

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

但是,一旦您使用const成员,您必须使用示例1的方式来完成此操作,例如,由于常量字段由值保持一个对象(与引用/指针字段)

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 
    } 
} 
+0

好的答案,只是在原始发布中添加example2而不是有效的C++ ,正如奥利在下面正确观察到的(http://stackoverflow.com/a/5856465/1284631) – user1284631 2012-07-31 09:13:02

0

初始化列表背后的动机是:我通常创建的唯一ID的方式如下。

这些字段必须初始化一次(由于它们的常量)。如果C++没有初始化列表,然后一个构造函数看起来是这样的:

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

没有初始化列表构造函数可以A类型的部分初始化对象传递给一个函数,该函数将没有办法知道哪些字段已被初始化。编译器/链接器检查风险太高,非常困难。

相关问题