C ++ NULL指针和const正确性

时间:2013-11-26 10:31:26

标签: c++ pointers c++11 const-correctness

我读到在删除指针数据成员之后检查类的析构函数是一个好习惯,如下所示:

if( 0 != m_pPointer)
{
    delete m_pPointer;
    m_pPointer= 0;
}

但是,我发现这会阻止您将const指针声明为数据成员,如下所示:

Type* const m_pPointer;

是不是将NULL分配给指针(如上例所示)是const正确性的障碍? 什么是最好的方法?保留所有内容const并停止为已删除的指针分配NULL或声明non-const指针,即使它们的地址永远不会更改?

4 个答案:

答案 0 :(得分:8)

这是不好的做法,原因如下:

  1. 在析构函数中将指针设置为null可能会掩盖双重破坏问题。良好的做法是尽早发现问题。
  2. delete之前检查指针是否为null只会增加不必要的代码。 delete通过什么都不做来处理空指针。好的做法是尽量减少代码量。

答案 1 :(得分:2)

保证删除空指针是安全的,因此空检查毫无意义。

如果一个类的成员是一个指向非const对象的const指针,那么你就是说指针值在包装对象的生命周期内不会改变 - 在这种情况下你应该只在指向的对象将比包装对象长或长的情况,包装对象永远不会指向不同的对象。

你有这个问题的事实只是意味着你在错误的地方使用了一个const指针。你声称在你的情况下指针值永远不会改变,但在你的例子中它显然是 - 它变为null。

答案 2 :(得分:1)

当您将静态库与来自两个不同的共享库(在Linux上)的全局或静态对象链接起来时,可能会导致一种奇怪的情况。后者将链接到同一个可执行文件。

每个共享的lib对象都插入了对构造函数和析构函数的调用,因此你将有一个对象和两个对同一对象的构造函数和析构函数的调用(实际上你将有2个对象映射到同一个地址)。

当您的应用在第二个析构函数中崩溃时,您可能会发现问题。 如果你为NULL,你将永远不会知道存在任何问题。

您的问题:除了上述问题,我认为您应该区分两种类型的指针: 见下面的课程:

class A{
  obj *x, *y;
  A(){
    x = new obj;
    y = NULL
  }
  ~A(){
    delete x;
    if(y)delete y; // the `if` here will save the calling and returning run time when NULL. 
  }
  void RecicleX(){
    delete x;
    x = new obj;
  }
  void InitY(){
    assert(y==NULL); //illegal to call init when already
    y = new obj;
  }
  void TermY(){
    assert(y); //illegal to call term when already inited
    delete y;
    y = NULL; //prevent crush in dtor if called after...
  } 
};

x始终存在,因此无需检查它,也不需要将其置零。 y可能存在也可能不存在,所以我认为删除后应该将其置空。 (您可能还想知道当前状态,例如assert

答案 3 :(得分:1)

“最好的办法”是:

class foo {
  std::unique_ptr<bar> m_pPointer;
public:
  foo(std::unique_ptr<bar> pPointer)
    : m_pPointer{std::move(pPointer)} {}
};

或对于const,

class foo {
  const std::unique_ptr<bar> m_pPointer;
public:
  foo(std::unique_ptr<bar> pPointer)
   : m_pPointer{std::move(pPointer)} {}
};

new,没有delete,没有析构函数。