为什么未初始化容器的行为与优化不同
Why is the behavior of uninitialized containers different with optimizations?
Given是一个具有以下元素的类:
std::array<Class*, 4> children;
在调试模式下,检查nullptr
上未初始化数组的元素会返回true
。
if(children[0]==nullptr)
然而,在发布模式下(启用了优化,无论O1、O3还是Os),检查返回false
。
元素似乎是以某种方式初始化的,但访问它们仍然会导致分割错误。为了避免这种行为,我必须用nullptr
元素显式初始化std::array
。
std::array<Class*, 4> children{{nullptr}};
为什么会出现这种情况?
编辑:在这种情况下使用的编译器是Apple LLVM 4.2 (Xcode 4.6.3)
std::array
与内置数组一样,是一个聚合,因此如果元素不是用户定义的类型(默认构造用户定义类型的元素),则不能保证自动初始化。不能依赖于具有任何特定值的元素。在您的情况下,可能是在调试(非优化)模式下,它从堆栈中分配碰巧已经清零的新空间,但启用了优化后,编译器可能会意识到它可以重用不再需要的空间,但保留旧数据。
在调试模式下,行为取决于编译器。有些编译器/调试器设置了魔术值(例如VS使用0xCDCDCD),有些则使用零(一点也不好)。在释放模式下,内存未初始化。这就是为什么它可以用一些编译器以调试方式工作,但永远不会在发布版中工作。
因为未初始化的(不是静态存储持续时间的)变量的内容是"不确定的"-不可能知道它会是什么,并且可能因各种因素而异。
编译器将为不同的优化级别生成不同的代码,这可能会导致内存中变量的布局不同。如果你想看到可预测的行为,那么你必须初始化变量。其他任何事情,都将取决于许多因素,包括优化级别,你得到的"结果"。
相关文章:
- 是否可以初始化不可复制类型的成员变量(或基类)
- C++使用整数的压缩数组初始化对象
- C++初始化基类
- 多成员Constexpr结构初始化
- 复制列表初始化的隐式转换的等级是多少
- 内联映射初始化的动态atexit析构函数崩溃
- 如何在C++中初始化嵌套类中的2个memeber
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 如何让MSVC编译器优化多步POD初始化?
- 具有必要副作用的静态初始化被优化掉了
- GCC缺少优化CTOR初始化器列表的机会
- 数组初始化优化
- 如何使用C++的字节码优化初始化嵌入式 Python 解释器
- 初始化的奇怪优化
- 优化地图上的初始化:转发密钥
- 为什么未初始化容器的行为与优化不同
- 使c++编译器优化到在map初始化时只调用构造函数一次
- 静态初始化器在库中会被优化掉
- 何时允许编译器优化auto+大括号样式的初始化
- 是std::映射表初始化优化