2017-10-08 84 views
2

在他的著作“编程,原理和用C++的做法” Bjarne的Stroustrup的介绍对314-316页(第9.4.4)成员初始化列表概念。他用下面的例子:使用成员初始化列表会使初始化稍微快一点吗?

// Simple Date (year, month, day) 

class Date 
{ 
public: 
    Date(int yy, int mm, int dd): y{yy}, m{mm}, d{dd} 
    { 
     //... 
    } 

private: 
    int y, m, d; 
}; 

在315页,他说:

我们可以这样写:

Date::Date(int yy, int mm, int dd) // constructor 
{ 
    y = yy; 
    m = mm; 
    d = dd; 
} 

但我们会在原则上首先必须默认初始化成员然后为它们分配值。

因此,我可以得出结论:使用成员初始化列表使代码稍微快一点?当然,没有人会注意到现代个人电脑。但是我打算使用C++进行嵌入式开发。

编辑:
我会进一步说明我的问题。实际上,“略快”我的意思是“所涉及的CPU周期较少”。
我也同意了这个特殊的例子潜在效率增长将接近落空。但是对于更大的类和结构,它可能会在微控制器上变得明显。

+4

使用'int's?没有任何区别。尝试一些沉重的课程。 – DeiDei

+0

如果没有副作用,则全部优化。 –

+0

使一个成员为const。现在哪种方式可行?这些决定涉及的性能不止于此。始终使用成员初始化程序列表作为默认值。 – StoryTeller

回答

5

在第二个示例中,您未初始化,您正在分配已经初始化的变量。在进入构造函数之前,变量被初始化(默认构造),所以你实际上设置了它们两次。

int没有任何具体的默认初始值,所以你没有注意到,但不同的代码试图做as in

#include <iostream> 
using namespace std; 

class Foo 
{ 
    int x; 

public: 
    Foo() : x(0) { cout << "Foo()" << endl; } 
    Foo(int x) : x(x) { cout << "Foo(int)" << endl; } 
    Foo& operator=(const Foo& o) { 
    cout << "Foo::operator=(const Foo&)" << endl; 
    this->x = o.x; return *this; 
    } 
}; 

class Bar 
{ 
    Foo foo; 
public: 
    Bar(const Foo& foo) { this->foo = foo; } 
    Bar(bool, const Foo& foo) : foo(foo) { } 
}; 

int main() { 
    cout << "Assigned in constructor" << endl; 
    Bar bar = Bar(Foo(5)); 
    cout << "Assigned in initializer list" << endl; 
    Bar bar2 = Bar(false, Foo(5)); 
} 

这将打印

Assigned in constructor 
Foo(int) 
Foo() 
Foo::operator=(const Foo&) 
Assigned in initializer list 
Foo(int) 

所以你看,他们绝对不当量。事实上,例如,您无法在构造函数中指定const字段

+0

Waw,有趣的代码片段!所以在你的例子中:(1)“在构造函数中赋值”导致对Foo构造函数的3次调用,以及(2)“在初始化符列表中赋值”只导致1次调用Foo构造函数。 –

+0

这3个调用Foo的构造函数=>这意味着有3个Foo对象坐在内存中的某处? –

+1

实际上,对于'Foo'构造函数和一个复制赋值运算符的两次调用,构造'Bar'时调用'Foo()'。然后调用'Foo(int)'来构造一个临时'Foo',它通过const引用传递给'Bar'中包含的'foo'的'operator =',它复制该值。然后临时销毁。成员初始化列表避免了这种情况,因为它是一个限制对象的初始化对象,因此编译器可以自由地执行任何他想做的事情。它们不仅仅是一段代码中的赋值,就像在构造函数中一样。 – Jack

1

C++标准规定 “缺省初始化”,如下所示:

[dcl.init]

为默认初始化类型T的对象是指:

- 如果T是 (如果T没有缺省构造函数或重载分辨率为 (1)(可能为cv-qualified)类类型(第9章),则调用T的默认 构造函数(12.1)(并且初始化为 ) 3.3)导致的模糊或在被删除的功能或 从初始化的上下文中)不可访问的;

- 如果T是 数组类型,每个元素是缺省初始化;

- 否则,不进行初始化。

你的班级成员是普通的,花园式的,int s。他们不是班级。他们不是阵列。因此,在int的情况下,默认初始化不执行任何操作。

我希望大多数编译器能够在你的两个例子中生成相同的代码。无论如何,这没有任何区别。

+0

谢谢@SamVarshavchik。你能想到一个重要的例子吗? –

+0

这是从标准的引用中指出的。如果类成员本身是一个(另一个)类,并且构造函数实际上做了某件事,那么它就很重要。 –

+0

谢谢@SamVarshavchik :-) –

相关问题