98

我有一个关于 const 指针的基本问题。我不允许使用 const 指针调用任何非 const 成员函数。但是,我可以在 const 指针上执行此操作:

delete p;

这将调用本质上是非常量“方法”的类的析构函数。为什么允许这样做?是否只是为了支持这一点:

delete this;

还是有其他原因?

4

5 回答 5

120

是为了支持:

// dynamically create object that cannot be changed
const Foo * f = new Foo;

// use const member functions here

// delete it
delete f;

但请注意,问题不仅限于动态创建的对象:

{
 const Foo f;
 // use it
} // destructor called here

如果不能在 const 对象上调用析构函数,我们根本就不能使用 const 对象。

于 2009-04-16T08:21:21.280 回答
53

这么说吧——如果不允许的话,不使用 const_cast 就无法删除 const 对象。

从语义上讲, const 表示对象应该是不可变的。但是,这并不意味着不应删除该对象。

于 2009-04-16T08:22:26.053 回答
5

构造函数和析构函数不应被视为“方法”。它们是初始化和拆除类对象的特殊结构。

'const pointer' 表示对象的状态在对象存活时对其执行操作时不会改变。

于 2009-04-16T08:30:32.240 回答
5

另一种看待它的方式: const 指针的确切含义是,您将无法对通过该对象或任何其他指针或对同一对象的引用可见的指向对象进行更改。但是当一个对象析构时,所有其他指向先前被现在删除的对象占用的地址的指针都不再是指向该对象的指针。它们存储相同的地址,但该地址不再是任何对象的地址(实际上它可能很快会被重用为不同对象的地址)。

如果 C++ 中的指针表现得像弱引用,那么这种区别会更加明显,即一旦对象被销毁,所有现存的指向它的指针都会立即设置为0. (这种东西在运行时被认为成本太高,无法强加于所有 C++ 程序,实际上不可能使其完全可靠。)

更新:九年后再读一遍,这是律师式的。我现在发现你最初的反应是可以理解的。不允许突变但允许破坏显然是有问题的。const 指针/引用的隐含契约是它们的存在将作为目标对象销毁的块,也就是自动垃圾收集。

通常的解决方案是使用几乎任何其他语言来代替。

于 2009-04-16T13:47:30.693 回答
5

我不允许使用 const 指针调用任何非 const 成员函数。

是的,你是。

class Foo
{
public:
  void aNonConstMemberFunction();
};

Foo* const aConstPointer = new Foo;
aConstPointer->aNonConstMemberFunction(); // legal

const Foo* aPointerToConst = new Foo;
aPointerToConst->aNonConstMemberFunction(); // illegal

您将指向非常量对象的 const 指针与指向 const 对象的非常量指针混淆了。

话说回来,

delete aConstPointer; // legal
delete aPointerToConst; // legal

由于此处其他答案已经说明的原因,删除任何一个都是合法的。

于 2011-10-13T18:16:41.993 回答