默认初始化 class 成员总是可取的吗?
Is default initializing class members always advisable?
一般建议避免在 class/struct 中获取未初始化的成员。考虑以下示例。
struct Foo
{
Foo(){}
int bar;
}
为了听从建议,我必须显式初始化 bar(例如 int bar{};
)。
但是,如果我总是通过在构造后立即为其赋值来初始化成员(让我们忘记将赋值作为构造函数参数传递)会怎样?我是否仍应遵循上述建议?如果没有开销,我仍然会这样做。但是,即使可以忽略不计,由于未使用的第一次初始化,也必须有相关的运行时开销。
初始化成员变量导致更稳定和可预测的class操作;对象不可能处于未知或不一致的状态。另一方面,某些操作可能相对较慢,如果您知道您的程序逻辑不会让成员长时间处于未初始化状态,那么您当然可以离开它们。在 C 中,没有构造函数来填充这些成员,但人们一直以来都在用 C 成功编程。
初始化 int
的成本不足以让 99.9% 的时间都值得担心。
总的来说,我的首要任务是安全而不是性能(我个人因奇怪的 UB 问题而不是性能问题遭受的痛苦更多)。
在这种特殊情况下,我建议初始化所有成员(尤其是 POD 类型)。最好在线执行此操作,因为这是您可以执行此操作的最早位置。这是一个很容易养成的习惯,比确保已初始化所有变量更容易。
然后衡量你的代码。如果事实证明您的瓶颈之一是 int
(或其他 POD 类型)成员的初始化(如果是这种情况,我会 非常 感到惊讶),那么是的,看看你在哪里进行了不必要的初始化并删除它们。
首先,您应该关心程序的安全性和正确执行。应该在分析和识别性能后进行优化 bottlenecks.There 俗话说 Premature Optimization Is the Root of All Evil
尽管很多人认为在定义时进行初始化是个好主意,但在 C++ 中这样做是有原因的。
原因就是额外的冗余赋值。但是当 bar
不仅仅是一个 int
并且具有更重的构造函数时,您只需要担心它,因为:
- 编译器有时会优化掉冗余赋值。
- 默认初始化通常成本低;但当然应该检查
所以这一切都回到了 bar
是否初始化成本高昂。
如果是,我建议你不要默认初始化,而是尝试在你的成员初始化列表中初始化它,如果这样做是:
- 可能,并且
- 不会抛出错误,或者您至少知道捕获异常的方法
如果这不是一个好主意,那么我建议使用 pointers 或 references 完全不初始化并使用成员函数在必要时这样做;
如果这也不是一个好主意,那么我建议在结构的构造函数中进行赋值,但尽量使 bar
的默认初始化尽可能不那么昂贵.
您还需要考虑初始化此对象的时间。如果你的程序是一个long-运行软件,那么尽可能在启动时初始化它;但当然,这些情况需要有关程序本身的更多详细信息。
我数不清有多少次没有初始化某些东西而搞砸了我的软件操作。通过初始化,您还可以防止使用您的 class 的任何其他人遇到同样的问题。此外,您不想假设其他人会像您一样练习良好的编码技术并在使用前初始化变量。
一般建议避免在 class/struct 中获取未初始化的成员。考虑以下示例。
struct Foo
{
Foo(){}
int bar;
}
为了听从建议,我必须显式初始化 bar(例如 int bar{};
)。
但是,如果我总是通过在构造后立即为其赋值来初始化成员(让我们忘记将赋值作为构造函数参数传递)会怎样?我是否仍应遵循上述建议?如果没有开销,我仍然会这样做。但是,即使可以忽略不计,由于未使用的第一次初始化,也必须有相关的运行时开销。
初始化成员变量导致更稳定和可预测的class操作;对象不可能处于未知或不一致的状态。另一方面,某些操作可能相对较慢,如果您知道您的程序逻辑不会让成员长时间处于未初始化状态,那么您当然可以离开它们。在 C 中,没有构造函数来填充这些成员,但人们一直以来都在用 C 成功编程。
初始化 int
的成本不足以让 99.9% 的时间都值得担心。
总的来说,我的首要任务是安全而不是性能(我个人因奇怪的 UB 问题而不是性能问题遭受的痛苦更多)。
在这种特殊情况下,我建议初始化所有成员(尤其是 POD 类型)。最好在线执行此操作,因为这是您可以执行此操作的最早位置。这是一个很容易养成的习惯,比确保已初始化所有变量更容易。
然后衡量你的代码。如果事实证明您的瓶颈之一是 int
(或其他 POD 类型)成员的初始化(如果是这种情况,我会 非常 感到惊讶),那么是的,看看你在哪里进行了不必要的初始化并删除它们。
首先,您应该关心程序的安全性和正确执行。应该在分析和识别性能后进行优化 bottlenecks.There 俗话说 Premature Optimization Is the Root of All Evil
尽管很多人认为在定义时进行初始化是个好主意,但在 C++ 中这样做是有原因的。
原因就是额外的冗余赋值。但是当 bar
不仅仅是一个 int
并且具有更重的构造函数时,您只需要担心它,因为:
- 编译器有时会优化掉冗余赋值。
- 默认初始化通常成本低;但当然应该检查
所以这一切都回到了 bar
是否初始化成本高昂。
如果是,我建议你不要默认初始化,而是尝试在你的成员初始化列表中初始化它,如果这样做是:
- 可能,并且
- 不会抛出错误,或者您至少知道捕获异常的方法
如果这不是一个好主意,那么我建议使用 pointers 或 references 完全不初始化并使用成员函数在必要时这样做;
如果这也不是一个好主意,那么我建议在结构的构造函数中进行赋值,但尽量使 bar
的默认初始化尽可能不那么昂贵.
您还需要考虑初始化此对象的时间。如果你的程序是一个long-运行软件,那么尽可能在启动时初始化它;但当然,这些情况需要有关程序本身的更多详细信息。
我数不清有多少次没有初始化某些东西而搞砸了我的软件操作。通过初始化,您还可以防止使用您的 class 的任何其他人遇到同样的问题。此外,您不想假设其他人会像您一样练习良好的编码技术并在使用前初始化变量。