13

代码示例应该解释一些事情:

class A
{
    B* pB;
    C* pC;
    D d;

    public : 
    A(int i, int j) : d(j)
    {
        pC = new C(i, "abc");
    } // note pB is not initialised, e.g. pB(NULL)

    ...
};

显然 pB 应该被显式初始化为 NULL 以确保安全(并且清晰),但是,就目前而言,在构建 A 之后 pB 的值是多少?它是默认初始化(为零?)还是不初始化(即不确定和内存中的任何内容)。我意识到 C++ 中的初始化有很多规则。

我认为它不是默认初始化的;在 Visual Studio 中以调试模式运行时,它已将 pB 设置为 0xcdcdcdcd - 这意味着内存已新建(在堆上)但未初始化。但是在释放模式下,pB 总是指向 NULL。这只是偶然,因此不值得依赖吗?还是这些编译器为我初始化它(即使它不在标准中)?在 Solaris 上使用 Sun 的编译器编译时,它似乎也为 NULL。

我真的在寻找对标准的具体参考来说明一种或另一种方式。

谢谢。

4

7 回答 7

12

以下是标准的相关段落:

12.6.2 初始化基和成员 [class.base.init]

4 如果给定的非静态数据成员或基类不是由
mem-initializer-list 中的 mem-initializer-id 命名,则

-- 如果实体是(可能是 cv 限定的)类类型(或其数组)或基类的非静态数据成员,并且实体类是非 POD 类,则实体是默认初始化的(dcl.init)。如果实体是 const 限定类型的非静态数据成员,则实体类应具有用户声明的默认构造函数。

--否则,实体未初始化。如果实体是 const 限定类型或引用类型,或者是(可能是 cv 限定的)POD 类类型(或其数组),包含(直接或间接)const 限定类型的成员,则程序是格式不正确。

在对类 X 的构造函数的调用完成后,如果成员

的 X 既没有在构造函数的 mem-initializers 中指定,也没有
默认初始化,也没有在
构造函数的主体执行期间初始化,该成员具有不确定的值。

于 2009-07-17T16:35:38.670 回答
4

根据C++0x 标准第 12.6.2.4 节,对于您的指针变量,如果您没有将其包含在初始化列表中并且您没有在构造函数的主体中设置它,那么它具有不确定性价值。0xCDCDCDCD 和 0 是两个可能的此类值,其他任何值也是如此。:-)

于 2009-07-17T16:40:32.170 回答
1

我相信这是过去 C 时代的产物,当时您无法对分配的内存包含的内容抱有期望。随着标准向 C++ 发展,这个“约定”得以维持。随着 C++ 编译器的开发,各个作者自行“修复”这个问题。因此,您的里程可能会因您选择的编译器而异。

“0xcdcdcdcd”看起来是一种易于识别的模式,可以“帮助”调试您的代码。这就是它在发布模式下不显示的原因。

我希望这会有所帮助,祝你好运。

于 2009-07-17T16:22:17.497 回答
1

未初始化的指针基本上可以包含一个随机值,尽管一些编译器倾向于用 0 或其他可识别的值填充它们,尤其是在调试模式下。

恕我直言,这是由于 C++ 的“不为不使用的东西付费”的设计。如果您认为它不重要,编译器不需要为您初始化变量。当然,一旦你追逐了一个随机指针,你可能会发现下次初始化它是谨慎的......

于 2009-07-17T16:37:03.973 回答
0

未初始化的指针可以指向任何东西。一些编译器供应商会帮助你,让它们指向 0 或 0xcdcdcdcd 或其他任何东西。

为了确保您的代码安全且可移植,您应该始终初始化您的指针。为 0 或为有效值。

例如

C* pc = 0;

或者

C* pc = new C(...);

如果您总是将指针初始化为 0,那么这是安全的:

if (!pc) 
    pc = new C(...);

如果您不初始化,那么您将无法区分已初始化和未初始化的指针。

顺便说一句,C++ 中没有 NULL 这样的关键字。大多数编译器将 NULL 定义为 0,但使用它不被认为是可移植的。新的 c++0x 标准将引入一个新的关键字 nullptr,因此当它出现时,我们最终将拥有一个可移植的空指针常量。

于 2009-07-17T16:26:12.997 回答
0

pB 的值未定义。它可能始终是相同的值,也可能不同——通常取决于在分配 A 的特定实例之前内存中相同位置的内容。

于 2009-07-17T16:26:20.437 回答
0

我很少建议不要学习有关您正在使用的语言的知识,但在这种情况下,是否初始化 pB 并不是有用的信息。只需初始化它。如果它是自动初始化的,编译器会优化掉额外的初始化。如果不是,您已经添加了一条额外的处理器指令并防止了一大堆潜在的错误。

于 2009-07-17T17:20:49.173 回答