我一直在用c ++工作一段时间,但我不确定它们之间的区别
public : Thing(int _foo, int _bar): member1(_foo), member2(_bar){}
Run Code Online (Sandbox Code Playgroud)
和
public : Thing(int _foo, int _bar){
member1 = _foo;
member2 = _bar;
}
Run Code Online (Sandbox Code Playgroud)
我有一种感觉,他们做同样的事情,但这两种语法之间是否存在实际差异.其中一个比另一个更安全,它们是否以不同方式处理默认参数.
不完全习惯于第一个例子,所以如果我犯了错误,我道歉.
Luc*_*ore 63
他们是不一样的,如果member1和member2是非POD(即非P LAIN Ø LD d ATA)类型:
public : Thing(int _foo, int _bar){
member1 = _foo;
member2 = _bar;
}
Run Code Online (Sandbox Code Playgroud)
相当于
public : Thing(int _foo, int _bar) : member1(), member2(){
member1 = _foo;
member2 = _bar;
}
Run Code Online (Sandbox Code Playgroud)
因为它们将在构造函数体开始执行之前被初始化,所以基本上两次完成工作.这也意味着,如果这些成员的类型没有默认构造函数,那么您的代码将无法编译.
Pét*_*rök 13
第一个是推荐的最佳实践,因为它更惯用,并且避免重新初始化具有默认构造函数的类型的字段(即非基本类型).
当您只初始化构造函数体内的成员时,编译器会为您生成默认的成员初始化语句,如果可以,那么您最终会双重初始化它.在某些情况下,这可能不是什么大问题,但如果构造对象很昂贵,可能会造成严重的性能开销.
但是,没有(n显式定义或生成的)默认构造函数的用户定义类型无法以这种方式初始化,因此会产生编译器错误.const和引用字段也是如此 - 这些只能在成员初始化列表中显式初始化.
添加到PéterTörök的唯一答案是初始化列表是初始化对象的const成员的唯一方法,即:
class foo
{
public:
foo(int value)
: myConstValue(value)
{};
foo()
{
myConstValue = 0; // <=== Error! myConstValue is const (RValue), you can't assign!
};
private:
const int myConstValue;
}
Run Code Online (Sandbox Code Playgroud)
在您的示例代码中,第一个是构造函数初始化中的,第二个是构造函数体内的赋值。
构造函数初始化列表是执行所有成员初始化的最佳方法,因为它可以提高性能。
class A
{
string name;
public:
A(string myname):name(myname) {}
}
Run Code Online (Sandbox Code Playgroud)
在上述情况下,编译器不会创建临时对象来进行初始化。但在以下情况下:
A::A()
{
name = myname;
}
Run Code Online (Sandbox Code Playgroud)
创建一个单独的临时对象,并将该临时对象传递给string的赋值运算符来赋值给name。然后临时对象就被销毁了,效率不太高。
注意:引用或 const 成员必须在构造函数初始化列表中初始化。它们不能在构造函数的主体中“分配”。