为什么在初始化列表中分配数据时没有创建额外的副本?
Parashift 很好地解释了初始化列表,但没有解释 <强>为什么在构造函数主体中分配之前会创建变量的额外副本,但通过初始化列表分配时不会创建额外的副本。
我什至遇到过使用 ++i 而不是 i++ 的建议,因为前者可以避免在赋值之前创建临时 i 。在 ctor 主体中分配的 POD 是否相同?在赋值之前创建临时变量?
换句话说,为什么编译器需要创建变量的额外副本?为什么不能直接给变量赋值?
为什么?
Parashift explains initialization lists well, but does not explain why an extra copy of a variable is created before assignment in the ctor body, but no extra copy is created when assigned through an initialization list.
I've even come across advice of using ++i instead of i++ because the former avoids creation of a temporary i before assignment. Is it the same for POD's assigned in a ctor body? A temp variable gets created before the assignment happens?
To put it another way, why does the compiler need to create an extra copy of a variable? Why can't it just assign the variable directly?
Why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
请考虑以下内容:
X()
构造函数与您所说的相同:首先,调用
C
构造函数来构造member
数据成员。然后执行X
的主体,创建第二个临时C
对象并将其分配给member
,然后销毁该临时对象。请注意,这仅适用于自动初始化的类型。如果
member
的类型为int
或 POD 类类型(作为示例),则当X
构造函数的主体为进入。对于此类类型,从性能角度来看,是在初始化列表中初始化数据成员还是在构造函数主体中分配给数据成员并不重要;差异完全是风格上的。在可能的情况下,为了保持一致性,仍应首选初始化列表。
Consider the following:
The
X()
constructor is the same as if you had said:First, the
C
constructor is called to construct themember
data member. Then the body ofX
is executed, a second, temporaryC
object is created and assigned tomember
, then the temporary is destroyed.Note that this is only the case for types that are initialized automatically. If
member
was of typeint
or of a POD class type (as examples), it would be uninitalized when the body of theX
constructor is entered.For such types it doesn't really matter from a performance standpoint whether you initialize the data member in the initialization list or assign to the data member in the body of the constructor; the difference is entirely stylistic. Where possible, the initialization list should still be preferred for the sake of consistency.
要解决您的第一个问题,特别是关于副本的问题(不涉及“++i”与“i++”):
构造函数是一个函数,并且它有参数。这些参数是作为参数传递的变量的副本(除非使用通过引用传递)。您现在可以操纵此副本或用它执行任何其他操作。然后,当您分配时,您将获取该参数的副本(可操作的可能性)并将其分配给成员变量。当您使用初始化列表时,编译器可以在没有此副本的情况下立即优化赋值,因为除了初始化之外,您不会将其用于任何其他用途(并且在将其分配给成员变量之前无法对其进行修改)。
To address your first question specifically regarding the copy (without touching on "++i" vs "i++"):
The constructor is a function, and it has parameters. These parameters are copies of the variables passed as parameters (unless passing by reference is used). You can now manipulate this copy or do anything else with it. Then when you assign, you take this copy of the parameter (possibility manipulated) and assign it to the member variable. When you use an initialization list, the compiler can optimize the assignment immediately without this copy, as you will not be using it for anything but the initialization (and cannot modify it before assigning it to the member variable).
因为赋值是在初始化之后进行的。换句话说,赋值是可选的,但初始化是强制性的。您可能不会注意到 POD 有太大差异。但这同样适用于用户定义的数据类型。
同样,对于 POD 来说这并不重要。但对于用户定义的类,
i++
确实会创建一个临时副本。所以最好使用++i
。Because assignment follows initialization. In other words, assignment is optional, but initialization is mandatory. You may not notice much difference for PODs. But the same holds true for user defined data types.
Again for PODs it doesn't matter much. But for user defined classes,
i++
does create a temporary copy. So it's better to use++i
.