删除指向const的指针(T const *)


89

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

delete p;

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

delete this;

还是还有其他原因?

Answers:


112

支持:

// 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对象。


21
+1以使您的编辑最新。我认为这是真的原因。const对象的自动析构函数调用-与delete f几乎相同;其中f-常量上的指针。
bayda

const Foo * fFoo const * f不是指向Foo的const指针。对const Foo来说更辛苦了。Foo * const f 是指向Foo的const指针。
user11373693 '19

48

这么说吧-如果它未被允许就没有办法删除const对象不使用的const_cast。

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


3
析构函数可以以相当暴力的方式对对象进行变异,因此这一定是我以前不知道的“不可变”一词的某种奇怪用法……
DarthGizka,2016年

1
@DarthGizka不,析构函数将您从有对象的状态带到没有对象的状态。C ++没有定义任何观察“销毁”后销毁的方法
Caleth

@ Caleth:该标准可能不允许您在其析构函数运行完毕后查看该对象,但是您当然可以查看该破坏所造成的副作用。因此,可以很容易地安排环境以使“不可变的”对象的变化可观察到。在美国,谋杀罪在没有尸体的情况下很难提起诉讼,但仍然是谋杀案(可能还有其他证据足以定罪)。一样的区别。
DarthGizka

6

我不允许使用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指针与指向const对象的非const指针混淆了。

话说回来,

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

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


5

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

“常量指针”用于指示在对象处于活动状态时对其执行操作时不会更改其状态。


5

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

如果C ++中的指针表现为弱引用,即当对象被销毁时,指向该对象的所有现有指针将立即设置为,则这种区别将更加明显0。(这种情况在运行时被认为过于昂贵,无法强加于所有C ++程序,并且实际上不可能使其完全可靠。)

更新:九年后读回这本书,很像律师。我现在发现您的原始反应是可以理解的。禁止突变但允许破坏显然是有问题的。const指针/引用的隐含约定是,它们的存在将充当破坏目标对象(即自动垃圾回收)的障碍。

通常的解决方案是改用几乎所有其他语言。


如果您无法销毁指向const的指针所指向的内容,那么您如何处理std::unique_ptr<const T>结尾的生命呢?
卡雷斯(Caleth)'18

@Caleth,那么在C ++中将没有解决方案。那只是一般问题的一个例子:在C ++中,const修饰符的意思是“您不能变异目标,除非从某种意义上说,您可以完全破坏目标并使所有其他对该目标的引用变为无效,并提供未定义行为的来源”。这就是为什么我认为这种问题应作为考虑其他语言的提示。它具有UB孔,不采取其他基本方法就无法解决。
Daniel Earwicker
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.