C++:我应该在构造函数体中将分配给指针成员的指针初始化为NULL吗?

12

假设我有:

// MyClass.h
class MyClass
{
  public:
    MyClass();

  private:
    Something *something_;
}

// MyClass.cpp
MyClass::MyClass()
{
  something_ = new Something();
}

在MyClass构造函数的初始化列表中,我应该将something_初始化为NULL(或0)吗?还是因为我在构造函数的主体中对其进行赋值,所以这不必要?推荐采用什么做法?


8
为什么不直接在一开始就初始化指针呢?MyClass::MyClass() : something_(new Something()) - Fred Larson
哦,那是最佳实践吗? - User
3
在构造函数中,始终优先选择初始化而非赋值。同时,使用像shared_ptrscoped_ptr这样的智能指针来代替原生指针,以便于即使在异常情况下也能自动清除。 - Fred Larson
那么,如果 something_ 只在 MyClass 内部使用,使用 shared_ptr 还是 scoped_ptr 最合适? - User
3个回答

12

通常情况下,你只需要在初始化列表或函数体中分配一次,除非函数体的初始化可能会发生变化,或者有前提代码:

MyClass::MyClass() 
{
   //this code must happen first
   // _now_ max is known
   something_ = new Something(max);
}

MyClass::MyClass() 
{
   if (max) 
       something_ = new Something(max);
   else
       something_ = NULL;
}

MyClass::MyClass() 
    : something_(new Something()) 
//as pointed out in the comments, use smart pointers
{
}

5
在初始化列表中使用动态分配的结果来初始化指针数据成员是不好的做法。出现太多问题了。例如,如果在构造其他数据成员时抛出异常,你如何知道已初始化哪些数据成员,以便销毁动态分配的对象?即使使用函数try块,也不知道构造失败的位置。(当然,应该使用智能指针,在这种情况下,在初始化列表中进行动态分配是可以的,但是使用普通指针时要小心)。 - James McNellis
1
@James:当然,使用智能指针而不是原生指针是更好的选择。(哈,你刚刚编辑了你的评论来说这个。) - Fred Larson
如果我需要创建两个不同的对象,而第一个对象需要第二个对象作为参数,我该怎么做?在这种情况下,是否可以使用初始化器,还是与您示例中的max函数一样呢?(例如:: something_(new Something()), somethingElse_(new SomethingElse(something_))... - User
2
@用户:初始化程序将按照成员声明的顺序运行,而不是按照初始化程序声明的顺序运行。因此,如果您按正确顺序声明成员,则可以具有这些依赖关系。 - Fred Larson
1
回应 James 的评论:我认为任何存储 new 结果的类都应该最多这样做一次,然后在初始化列表中执行它就可以了。有多个动态分配不符合异常正确性的规模,并且这是您需要部署单一责任资源管理器类的明确迹象。 - Kerrek SB

2

一般来说,不行。但是如果在构造函数中使用指针之前未初始化,则会出现未定义的行为。然而,你面临的最大问题是——如果构造函数中抛出异常,则其析构函数不会被调用。因此,想象一下你有两个对象的指针,第一个对象的分配成功,而第二个分配失败,那么你就会出现资源泄漏的情况。这可以通过使用“智能”指针来解决。但在这种情况下,它们将在初始化列表中初始化,如果你不想给它们分配两次值,那么最好在其中分配内存而不是在构造函数体中。


我没有考虑到潜在的异常安全问题。 - Mooing Duck

1

如果你在构造函数体中立即初始化,那么就没有必要了,但是如果初始化不那么明显,为什么不将其NULL以避免意外访问未初始化的变量呢。

  • 最小化性能开销
  • 节省大量的调试/故障排除时间,避免疯狂的错误猎捕

“疯狂的错误猎杀”——确实如此。我现在正在寻找资源泄漏(一个Windows用户对象),而且最令人困扰的是初始化列表中的new调用:在初始化列表的“原子”世界中不存在前后顺序。 - Wolf

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