2009-07-17 137 views
8

代码示例应该解释的事情:C++:成员指针初始化?

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,明确地是安全的(和明确的),但是,因为它的立场,什么是PB的建设后的价值?它是否默认初始化(它是零?)还是不存在(即不确定和内存中的任何内容)。我意识到在C++中初始化有一些公平的规则。

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

我真的很想找一个具体的标准来说一种或另一种说法。

谢谢。

+4

不确定(和一些编译器会警告),但我没有C++标准方便... – ephemient 2009-07-17 16:21:11

+4

B是一个随机指向野外的指针。注意。在调试模式下,大多数编译器会将其初始化为NULL(据说有助于调试)。但在发布模式下,它将具有先前在内存中的值。 – 2009-07-17 16:25:32

回答

11

下面是相关通道fromt他标准:

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

4如果一个给定的非静态数据成员或 基类不是通过在 MEM-初始化-list中的MEM-
初始化-ID命名,然后

- - 如果该实体是 构件(可能CV修饰)0123非静态数据类类型(或其数组)或基类,实体类 是非POD类,实体是默认初始化的(dcl.init)。 如果实体是一个const限定类型的非静态数据成员,实体类应该有一个用户声明的默认构造函数。

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

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

X的

既不在 构造的MEM-初始化规定,也不
默认初始化,也不执行期间初始化
的构造函数体,成员有 不确定值。

+2

所以它是未初始化的,并且可以指向任何东西。内容可以通过实现来填充,即debugheap库的fdfdfdfd。 – xtofl 2009-07-17 17:24:10

1

我相信这是一个很好的旧C时代的工件,当你无法预期alloc'd内存包含什么时。随着标准发展到C++,这个“约定”得以保留。随着C++编译器的开发,各位作者自行解决这个问题。因此,您的里程可能会因您选择的编译器而异。

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

我希望这有助于一点点和祝你好运。

0

未初始化的指针可指向任何内容。一些编译器厂商会帮助你,并使它们指向0或0xcdcdcdcd或其他。

为了确保您的代码安全可靠,您应始终初始化您的指针。无论是0还是有效值。

例如

C* pc = 0; 

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

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

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

如果你不初始化,然后你有没有讲些初始化方式和未初始化的指针分开。

另一方面,C++中没有这样的关键字为NULL。大多数编译器将NULL定义为0,但它不被认为是可移植的。新的C++ 0x标准将引入一个新的关键字nullptr,所以当它出现时,我们终于有一个可移植的空指针常量。

0

pB的值是未定义的。它可能会也可能不是一致的价值 - 通常取决于之前分配特定A实例之前在内存中的相同位置。

0

未初始化的指针允许基本上包含一个随机值,尽管一些编译器倾向于用0或其他可识别的值填充它们,尤其是在调试模式下。恕我直言,这是由于C++的“不支付你不使用的”设计。如果你认为它不重要,编译器不需要花费为你初始化变量。当然,一旦你追逐了一个随机指针,你可能会发现下一次初始化它是审慎的...

4

根据C++0x standard第12.6.2.4节,如果你的指针变量,如果你不喜欢将其包含在初始化程序列表中,并且不将其设置在构造函数的主体中,则它具有不确定的值。 0xCDCDCDCD和0是两个可能的值,就像其他的一样。 :-)

0

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