【问题标题】:For a class constructor, what is the difference between the assignment via parentheses or the equal sign? [duplicate]对于类构造函数,通过括号赋值或等号赋值有什么区别? [复制]
【发布时间】:2012-12-29 12:35:42
【问题描述】:

可能重复:
Initializing fields in constructor - initializer list vs constructor body

在我参加的一次讲座中,讲师用 C++ 简要介绍了非默认类构造函数。他特别指出,一个版本优于另一个版本。他举了两个例子:

Point::Point(double x, double y, double z)
: x_(x), y_(y), z_(z)
{}

Point::Point(double x, double y, double z)
{ x_= x; y_= y; z_= z; }

他提到第一个示例(使用括号)是编写构造函数的首选方式。

我的问题是:有什么区别,为什么重要?第一个优于第二个在什么方面?

【问题讨论】:

标签: c++ class constructor


【解决方案1】:

原因是第一个不是赋值,是初始化,第二个代码其实和这个是一样的:

Point::Point(double x, double y, double z)
: x_(), y_(), z_()
{ x_= x; y_= y; z_= z; }

也就是说,所有成员在被分配之前都在这里默认初始化。当它们的类型没有默认构造函数时,这不起作用。例如:

class Foo {
    Foo(); // Private, undefined constructor
public:
    Foo(int) { }
};

class Bar {
    int& i;
    Foo f;

public:
    Bar() { i = 0; f = Foo(0); }
};

此代码不起作用,因为 Bar 的构造函数依赖于 f 的默认构造函数和 i 的初始化程序的存在,两者都不存在。

但是即使所有成员都是默认可构造或可初始化的,仍然建议在初始化列表中初始化它们而不是通过构造函数中的赋值:如果没有别的,它会更有效(因为否则你将执行冗余操作在某些情况下可能会很昂贵)。

【讨论】:

    【解决方案2】:

    在进入构造函数主体之前,第一个复制构造成员。注意:这是 C++ 中称为构造函数initializer list 的更大主题的一部分。在初始化列表中表示某些成员变量类型是强制,其中包括引用成员、具有非默认构造的成员(即其构造函数需要参数)和 const 成员。问题中提出的案例中的用法是调用复制构造,而不是默认构造,然后是体内赋值,这使我们...

    第二个默认-在进入构造函数主体之前构造成员,然后在主体中分配它们的值。这仅适用于支持默认构造的成员。

    在这两个中,第一个通常是首选,特别是对于具有昂贵的默认初始化的复杂数据类型。由于即将发生的后续分配,所述初始化可能会部分或完全浪费。您通常最好放弃这一点并改用复制构造。注意:所有内在数据类型(intfloat、指针等)都支持复制构造。

    【讨论】:

      【解决方案3】:

      第二种方式执行默认构造,然后是赋值。

      如果默认构造函数不可用,它将无法工作,而且无论哪种方式,它都可能不会那么便宜。

      另外,第一个方法可以调用显式构造函数,而第二个则不能。

      【讨论】:

        猜你喜欢
        • 2012-07-27
        • 1970-01-01
        • 1970-01-01
        • 2015-03-03
        • 2014-05-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-12
        相关资源
        最近更新 更多