强制本地变量默认初始化
Forcing local variables to be default-initialized
在C++中,默认情况下,纯旧数据(POD)局部变量未初始化。不过,我注意到这会导致错误,因为试图读取未初始化变量的值是未定义的行为。
有没有办法强制编译器自动初始化所有的局部变量?也许是内置了此功能的编译器,或者是通用编译器(如GCC或Clang)的编译器开关?我可以接受Gnu扩展;它不一定是标准的。
我希望变量被默认初始化,这意味着int
将被设置为0。
我厌倦了将所有本地int
和私有类字段分配给0。
我所知道的没有开关可以做,即使它确实存在,它也只是一个"调试"功能,不能在生产代码中使用。
示例:电子围栏库可以选择将内存初始化为0或0xff
EF_FILL当设置为0到255之间的值时,分配的内存的每个字节都初始化为该值。这可以帮助检测未初始化内存的读取。当设置为-1时,一些内存将填充零(大多数系统的操作系统默认值),而一些内存将保留上次使用时写入的值。
(仅适用于分配的内存,不适用于自动内存)。
依赖一个未在标准中定义为/的开关会使代码不可移植。在某个时刻,有人会使用您的代码在其他平台上进行交叉编译,但这将失败。
作为一种帮助/保护,像Coverity这样的一些工具(注意:我不隶属于这家公司)可以检测代码中未初始化的POD成员。可能也有免费的工具可以做同样的事情。
那么,如果有一个或两个POD成员(c++11),我会怎么做:
class Foo
{
...
private:
int x = 0;
int y = 0;
};
如果你有无数个成员,也许可以创建一个POD类/结构,创建一个具有这种类型的成员,并使用最有效的初始化方法将其初始化为0:
class Foo
{
...
private:
struct Pod
{
int x,y,z,whatever;
};
Pod m = {0};
};
这迫使访问m.x
等成员。。。不透明
或者(可能有点麻烦,但有效),创建一个POD结构,然后从中继承您的类。您现在可以在默认构造函数中对POD结构的大小应用memset
struct Pod
{
Pod()
{
std::memset(this,0,sizeof(Pod));
}
int x,y,z,whatever;
};
class Foo : private Pod
{
public:
...
private:
std::string name;
std::vector<int> elements;
};
sizeof(Pod)
值确保memset
仅将Pod
的成员设置为0。
如果Pod
来自无法更改的C结构,则可以在Foo
构造函数中移动memset
语句,保持sizeof(Pod)
有一个建议是用零初始化的本地变量编译linux内核,请参阅今年linux.conf的演示https://youtu.be/FY9SbqTO5GQ?t=742
为了实现这一点,演示者团队使用了一个实验性的gcc开关finit-local-vars
,这里有补丁https://gcc.gnu.org/ml/gcc-patches/2014-06/msg00615.html
我希望这将最终合并到gcc主分支并被广泛采用。实际上,我看到的每一个代码风格指南都要求C/C++程序员在定义变量的任何地方进行显式零赋值= 0
。这是一项容易出错且毫无意义的猴子工作。
EDIT 2022:在GCC 12 中添加了一个开关-ftrivial-auto-var-init
- 使用 std::分配器在 constexpr 中进行默认初始化
- 为什么对象默认初始化,但基元不在C++?
- 为什么std::atomic的默认构造函数不默认初始化底层存储值
- 两个成员,在Base中默认初始化,可能在Derived中非默认初始化
- 默认初始化无法正常工作
- C++11默认初始化/值初始化/直接初始化
- make_shared是否对每个成员变量执行默认初始化(零初始化)
- 是否可以默认初始化具有已删除默认构造函数的类类型
- 对象成员数组C++默认初始化
- POD成员默认初始化无括号
- 如何在不使用 new 的情况下进行默认初始化
- 有没有办法欺骗 std::make_shared 使用默认初始化
- 枚举类默认初始化
- 是默认的构造函数和默认初始化
- 为什么在C 中不允许使用括号的默认初始化
- 默认初始化的含义在C 11中发生了变化
- Main()函数中的默认初始化
- WINHTTP_CURRENT_USER_IE_PROXY_CONFIG默认初始化
- 强制本地变量默认初始化
- 默认初始化混乱