【发布时间】:2009-11-26 20:00:48
【问题描述】:
Sphere() : theRadius(1.0)
{
}
为什么使用初始化器编写的构造函数(上)比在其主体中初始化数据成员的构造函数(下)更好?
Sphere()
{
theRadius = 1.0;
}
【问题讨论】:
标签: c++
Sphere() : theRadius(1.0)
{
}
为什么使用初始化器编写的构造函数(上)比在其主体中初始化数据成员的构造函数(下)更好?
Sphere()
{
theRadius = 1.0;
}
【问题讨论】:
标签: c++
所有成员在进入构造函数的主体之前被初始化。如果您没有在初始化列表中提供初始化程序,那么它们是默认构造的。
在您的第一个示例中发生以下情况:
theRadius 初始化为 1.0在您的第二个示例中发生以下情况:
theRadius 已初始化theRadius
对于像整数和浮点数这样的简单类型,这并不重要。但是,如果您的成员是具有非平凡构造函数/复制构造函数的对象,那么使用初始化列表方法会更有效。
【讨论】:
如果您没有显式初始化字段,编译器将尝试运行它们的默认构造函数。如果它们没有可访问的默认构造函数,您的源代码将无法编译:
class Field {
public:
Field(int x) {}
};
class Test {
Field f;
public:
Test() { // compiler error here. `Field` doesn't have default constructor.
f = Field(10);
}
};
int main ( ) {
Test t;
}
如果他们确实有一个默认构造函数,那么你调用它是不必要的,因为你正在调用正文中字段的另一个构造函数。
【讨论】:
在进入构造函数的主体之前,总是为对象属性调用构造函数。
如果自己不指定构造函数,会调用默认的,后面会用operator=改值。
这可能不是您想要的。
特别是,您不能更改构造函数主体内的const 属性的值。
你必须使用初始化列表。
【讨论】:
因为否则会调用对象的默认构造函数,然后设置值。
这只会调用字符串构造函数
class Foo{
std::string s;
Foo() : s("Hello World"){}
}
在哪里:
class Foo{
std::string s;
Foo(){
s = "Hello World";
}
}
会调用默认的字符串构造函数,然后将字符串的值设置为“Hello World”
【讨论】:
如前所述,对于非原始类型,它会有所不同。
这也是初始化 const 成员变量的唯一方法。
class MyClass
{
const int x;
public:
MyClass(int x)
{
this->x=x;
}
};
这不应该编译。
【讨论】:
正如其他人所说,将第一种形式用于具有非平凡构造的类型会更有效。
此外,第一种形式使您能够捕获使用 try/catch 块的函数形式初始化的成员对象(或基类)的构造函数中抛出的任何异常。例如:
MyObject() : memberObject(...)
try {
// my constructor
}
catch (...) {
// catches exceptions in try block AND memberObject constructor
}
这不是缺少一组括号。如果您确实在 try/catch 块周围放置了另一组括号,它将不会在 memberObject 构造函数中捕获异常,而只是在 try 块中。
【讨论】:
它主要用于初始化常量和引用变量,因为它们不能在构造函数体中初始化。
【讨论】: