C++类中指针成员变量的初始化

25

这可能听起来太基础,让人觉得我没有尽力去寻找答案,但是我发誓我搜索了大约20分钟,没有找到答案。

如果一个私有的C++类成员变量(非静态)是一个指针,并且在构造函数中没有被初始化(无论是通过初始化列表还是在构造函数中进行赋值),那么当类完全实例化时它的值会是什么?

奖励问题:如果以上问题的答案不是NULL,而我希望始终将一个特定的成员指针变量初始化为NULL,并且我有多个构造函数,我真的必须在每个构造函数中都写一个显式初始化吗?如果是这样,专业人士如何处理?他们肯定不会在所有构造函数中都为相同的成员变量放置冗余的初始化程序,对吧?

编辑:我希望我能在这里选择两个答案。Bleep Bloop 推荐的智能指针似乎是最优雅的方法,它得到了最多的赞。但由于我还没有在我的工作中使用智能指针,所以我选择了没有使用智能指针的最具说明性的答案。

6个回答

14

您的想法是正确的。如果您不对其进行初始化,它就可以是任何值。

因此,回答您的问题是,要么用某个值进行初始化,要么将其赋为NULL(在最新的C++标准中使用nullptr)。

class A
{
};


class B
{
private:
    A* a_;

public:
    B() : a_(NULL) { };
    B(a* a) : a_(a) { };
};

我们的默认构造函数将其设为NULL(如果需要,可以使用nullptr进行替换),第二个构造函数将用传递的值初始化它(这也不是保证一定是好的!)。


不错,谢谢,演示得很清楚。如果您有第三个构造函数,它没有以A*指针作为参数,那么它是否需要显式地将a_初始化为NULL?还是它能够以某种方式从您编写的无参构造函数的初始化列表中"链接"起来? - John Fitzpatrick
它还需要将其初始化为NULL / nullptr。如果我有多个需要进行公共初始化的构造函数,我倾向于实现一个私有的commonConstruct()方法,该方法为我执行默认初始化。 - Moo-Juice
NULL和0是一样的吗?B():a_(0){}能够产生相同的效果吗? - arjacsoh
@arjacsoh,是的,它会扩展成00L。不过,在C++11中,你实际上有一个nullptr关键字。最大的优点是,现在你可以区分一个指向null的指针和一个整数0:) - Moo-Juice
请问您能否提供一个链接,证实您的说法符合标准? - fex

8

这个值会没有初始化,所以你需要明确地将其初始化为nullptr

使用智能指针 (std::unique_ptr, std::shared_ptr, boost::shared_ptr, 等等) 可以避免需要显式初始化。


1
这肯定是更好的长期解决方案,我最终会使用智能指针。但在开始使用它们之前,我需要多了解一些关于它们的知识,所以我会采纳Moo-Juice的建议。 - John Fitzpatrick

1

值将未定义。

您可以拥有一个“终极”构造函数,它将初始化所有字段,并添加仅使用部分参数的“快捷”构造函数,这些构造函数将传递这些参数到终极构造函数以及其余参数的默认值。


1
即使最受欢迎的答案在技术上是正确的,我建议更好的方法是在类本身中初始化变量。
class A
{
};


class B
{
private:
    A* a_ = nullptr;

public:
    B() : { };
    B(a* a) : a_(a) { };
};

1
任何未初始化指针的值都是垃圾值,它是一些随机的内存地址。
在你的构造函数中,你可以使用初始化列表来初始化你的指针。
简单明了。
MyClass::MyClass() : myPointer(nullptr)
{
}

试图引用未初始化的指针会触发未定义行为。因此,始终要初始化您的指针。


0
在C++中,您可以使用初始化列表语法将值初始化为成员变量。请参见以下内容:
class AnyClass
{
};
class Xyz
{
    int n;
    AnyClass *p;
    Xyz() : n(55), p(new AnyClass())
    {
        // constructor body
    }
    ~Xyz() { delete p; }
};

n 的值变为 55,并且指向新创建的 AnyClass 的指针被初始化到 p 中。请注意,它们没有分配给 np。它们被初始化到成员变量中。

使用 new 时,应使用 delete 进行删除。使用 new[] 时,应使用 delete[]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接