由于构造函数初始值设定项列表而优化
构造函数应该通过以下方式初始化其所有成员对象 如果可能的话,初始化列表。它比构建更有效 通过构造函数体内的赋值来构造函数。
有人可以解释一下,为什么在示例的帮助下使用初始值设定项列表更有效?
Constructors should initialize all its member objects through
initializer list if possible. It is more efficient than building the
constructors via assignment inside the constructor body.
Could someone explain, why it is more efficient to use the initializer list with the help of an example?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
考虑这个程序:
在我的系统(Ubuntu 11.10,g++ 4.6.1)上,该程序产生以下输出:
现在,考虑为什么要这样做。在第一种情况下,
C1::C1(int)
、a
必须先默认构造,然后才能调用C1
的构造函数。然后必须通过operator=
分配给它。在我的简单示例中,没有可用的int
赋值运算符,因此我们必须从 int 构造一个A
。因此,不使用初始化器的成本是:一个默认构造函数、一个 int 构造函数和一个赋值运算符。在第二种情况
C2::C2(int)
中,仅调用int
构造函数。无论默认A
构造函数的成本是多少,显然C2:C2(int)
的成本不会大于C1::C1( int)
。Or, consider this alternative. Suppose that we add the following member to
A
:然后输出将显示:
现在不可能一般地说哪种形式更有效。在您的特定类中,默认构造函数的成本加上赋值的成本是否比非默认构造函数更昂贵?如果是这样,那么初始化列表会更有效。否则就不是。
我曾经编写过的大多数类都可以在 init 列表中更有效地初始化。但是,这是一个经验法则,可能并不适用于所有可能的情况。
Consider this program:
On my system (Ubuntu 11.10, g++ 4.6.1), the program produces this output:
Now, consider why it is doing that. In the first case,
C1::C1(int)
,a
must be default-constructed beforeC1
's constructor can be invoked. Then it is must assigned to viaoperator=
. In my trivial example, there is noint
assignment operator available, so we have to construct anA
out of an int. Thus, the cost of not using an initializer is: one default constructor, oneint
constructor, and one assignment operator.In the second case,
C2::C2(int)
, only theint
constructor is invoked. Whatever the cost of a defaultA
constructor might be, clearly the cost ofC2:C2(int)
is not greater than the cost ofC1::C1(int)
.Or, consider this alternative. Suppose that we add the following member to
A
:Then the output would read:
Now is is impossible to say generally which form is more efficient. In your specific class, is the cost of a default constructor plus the cost of an assignment more expensive than a non-default constructor? If so, then the initialization list is more efficient. Otherwise it isn't.
Most classes that I've ever written would be more efficiently initialized in an init list. But, that is a rule-of-thumb, and may not be true for every possible case.
好吧,否则您将调用默认构造函数并然后执行赋值。这会长一步,并且可能会变得非常低效,具体取决于初始化的性质。
Well, otherwise you call the default constructor and then perform an assignment. That's one step longer and may get really inefficient depending on the nature of initialization.
因为它是直接初始化的,而不是默认初始化然后赋值。对于 POD 来说,这在性能方面可能并不重要,但如果类型构造函数正在执行繁重的工作,则会产生影响。
另外,在某些情况下,您必须使用init list,因此您应该始终这样做以保持一致性。
Because it initialises directly, instead of default initialising and then assigning. It likely won't matter performance-wise for PODs, but it will if the type constructor is doing heavy-weight work.
Also, in some cases you must use init list, so you should always do it for consistency.
来自 C++FAQ :
From the C++FAQ :
防止双重初始化。
现在分两种情况:
To prevent double initialization.
Now the two cases:
就 POD 类型而言,初始化和赋值应该是等效的,因为如果没有显式执行初始化,它们将保持未初始化状态,因此唯一的操作仍然是赋值。
对于具有默认构造函数和赋值运算符的类来说,情况有所不同:不是直接在正确的状态下创建对象,而是首先必须调用默认构造函数,然后调用赋值运算符(在构造函数体内)。这肯定比从一开始就使用正确的构造函数初始化对象要低效(两步而不是一步,第一步 - 默认构造 - 通常完全浪费)。
直接初始化还具有一个优点,即您可以确定,如果执行到达构造函数的主体,则所有各个字段都已处于“正确”状态。
As far as POD types are concerned, the initialization and the assignment should be equivalent, since they are left uninitialized if no initialization is performed explicitly, so the only operation remains the assignment.
Things are different for classes which have default constructors and assignment operators: instead of creating the object directly in the correct state, first the default constructor has to be called, and then the assignment operator (inside the body of the constructor). This is surely more inefficient than initializing the object with the correct constructor straight from the beginning (two steps instead of one, and the first step - default construction - is usually completely wasted).
The direct initialization also yields the advantage that you can be sure that, if the execution reached the body of the constructor, all the various fields are already in their "correct" state.
假设您的类中有一个 std::string 类型的数据成员。当执行此类的构造函数时,将自动调用默认的构造函数字符串类,因为对象是在构造函数主体之前初始化的。
如果要在构造函数体内分配字符串,则会创建一个临时对象并将其提供给字符串的赋值运算符。临时对象将在赋值语句结束时被销毁。如果在初始化列表中执行此操作,则不会创建临时对象。
Suppose you have a data member in your class which is std::string type. When the constructor of this class is executed, the default constructor string class would be called automatically because objects are initialized before the body of the constructor.
If you are assigning the string inside the body of the constructor, then a temporary object would be created and given to the string's assignment operator. The temporary object will be destroyed at the end of the assignment statement. If you do this in the initializer list, a temporary object will not be created.
因为如果您使用初始化程序列表,您所调用的是该对象的构造函数副本。
而如果您在构造函数体内初始化对象,则您正在执行赋值操作。
例子:
这里我调用 int 的复制构造函数。
在这里我调用operator=(const int&)。任务
通常,赋值比简单的复制执行更多的操作。
您还必须记住临时对象!
because if you are using the inizializer list what you are calling is the constructor copy of that object .
While if you initialize objects inside the constructor body you are doing an assignment.
example:
here i m calling the copy constructor of int.
while here i m calling the operator=(const int& ). the asignment
usually the asignment does more operation then a simple copy.
you must keep in account also temporary object!