C++初始化列表和内存分配

4
以下内容是否有效?
class myClass
{
   private:
     ...
     int m_nDataLength;
     boost::shared_array<int> m_pData;
     ...

   public:
     myClass(): ..., m_nDataLength(10), m_pData(new int[m_nDataLength]), ...
     {
     }
}

我猜初始化会按照构造函数中给定的顺序进行,这样理解对吗?如果不是,那么如果m_nDataLength的初始化发生在m_pData之后会发生什么?


2
请参见https://dev59.com/V3M_5IYBdhLWcg3ww2AQ。 - Luc Touraille
我没有注意到这个问题,我的问题似乎是这个问题的重复。感谢通知Luc。 - legends2k
3个回答

10

尽管你的示例中初始化确实按照你想要的顺序发生,但原因并非你所认为的那样:初始化按照类定义中数据成员的声明顺序发生。 这样做的原因是无论使用哪个构造函数创建对象,析构函数都必须以相反的顺序销毁成员。因此,必须使用一种与构造函数无关的方式来定义构造顺序。

这意味着,如果改为

class myClass
{
   private:
     ...
     int m_nDataLength;
     boost::shared_array<int> m_pData;

有人会更改你的代码为

class myClass
{
   private:
     ...
     boost::shared_array<int> m_pData;
     int m_nDataLength;

那么代码将会有一个错误。

我的建议是:

  • 编写你的构造函数,使初始化顺序不重要。
  • 如果你无法做到这一点(注意:在过去十年中,我遇到这种情况少于5次),则在声明数据成员时明确指出。

像这样表达应该就可以了:

class myClass
{
   private:
     ...
     int m_nDataLength;                 // Note: Declaration order
     boost::shared_array<int> m_pData;  //       matters here!

哇,感谢这里所有的答案。它解决了一个令人烦恼的问题,并让我眼前一亮 :)但是我投票支持这个答案是因为它详细。 - legends2k

9

初始化将按照类中的顺序初始化字段,因此:如果您更改了

private:
  ...
  int m_nDataLength;
  boost::shared_array<int> m_pData;

as

private:
  ...
  boost::shared_array<int> m_pData;
  int m_nDataLength;

无法工作。在构造函数中,顺序不适用。


5
不,类成员的初始化按照它们在类定义中出现的顺序进行。如果一个成员在初始化列表中出现,则该列表控制用于初始化该成员的表达式(即使它使用尚未初始化的成员),但它在初始化列表中的位置不影响其何时被初始化。

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