使用成员初始化列表会使初始化稍微快一点吗?
在他的著作“编程,原理和用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周期较少”。
我也同意了这个特殊的例子潜在效率增长将接近落空。但是对于更大的类和结构,它可能会在微控制器上变得明显。
在第二个示例中,您未初始化,您正在分配已经初始化的变量。在进入构造函数之前,变量被初始化(默认构造),所以你实际上设置了它们两次。
的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
字段
Waw,有趣的代码片段!所以在你的例子中:(1)“在构造函数中赋值”导致对Foo构造函数的3次调用,以及(2)“在初始化符列表中赋值”只导致1次调用Foo构造函数。 –
这3个调用Foo的构造函数=>这意味着有3个Foo对象坐在内存中的某处? –
实际上,对于'Foo'构造函数和一个复制赋值运算符的两次调用,构造'Bar'时调用'Foo()'。然后调用'Foo(int)'来构造一个临时'Foo',它通过const引用传递给'Bar'中包含的'foo'的'operator =',它复制该值。然后临时销毁。成员初始化列表避免了这种情况,因为它是一个限制对象的初始化对象,因此编译器可以自由地执行任何他想做的事情。它们不仅仅是一段代码中的赋值,就像在构造函数中一样。 – Jack
C++标准规定 “缺省初始化”,如下所示:
[dcl.init]
为默认初始化类型T的对象是指:
- 如果T是 (如果T没有缺省构造函数或重载分辨率为 (1)(可能为cv-qualified)类类型(第9章),则调用T的默认 构造函数(12.1)(并且初始化为 ) 3.3)导致的模糊或在被删除的功能或 从初始化的上下文中)不可访问的;
- 如果T是 数组类型,每个元素是缺省初始化;
- 否则,不进行初始化。
你的班级成员是普通的,花园式的,int
s。他们不是班级。他们不是阵列。因此,在int
的情况下,默认初始化不执行任何操作。
我希望大多数编译器能够在你的两个例子中生成相同的代码。无论如何,这没有任何区别。
谢谢@SamVarshavchik。你能想到一个重要的例子吗? –
这是从标准的引用中指出的。如果类成员本身是一个(另一个)类,并且构造函数实际上做了某件事,那么它就很重要。 –
谢谢@SamVarshavchik :-) –
使用'int's?没有任何区别。尝试一些沉重的课程。 – DeiDei
如果没有副作用,则全部优化。 –
使一个成员为const。现在哪种方式可行?这些决定涉及的性能不止于此。始终使用成员初始化程序列表作为默认值。 – StoryTeller