Удаление указателя на const (T const *) - PullRequest
80 голосов
/ 16 апреля 2009

У меня есть основной вопрос относительно константных указателей. Мне не разрешено вызывать любые неконстантные функции-члены, используя константный указатель. Однако мне разрешено делать это на константном указателе:

delete p;

Это вызовет деструктор класса, который по сути является неконстантным «методом». Почему это разрешено? Это просто для поддержки этого:

delete this;

Или есть какая-то другая причина?

Ответы [ 5 ]

102 голосов
/ 16 апреля 2009

Это для поддержки:

// 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

Если деструкторы нельзя вызывать для константных объектов, мы вообще не могли бы использовать константные объекты.

44 голосов
/ 16 апреля 2009

Скажем так: если бы не было разрешено, невозможно было бы удалить объекты const без использования const_cast.

Семантически const указывает на то, что объект должен быть неизменным. Это, однако, не означает, что объект не должен быть удален.

5 голосов
/ 16 апреля 2009

Другой способ взглянуть на это: точное значение константного указателя состоит в том, что вы не сможете вносить изменения в объект, на который указывает указатель, который будет виден через этот или любой другой указатель или ссылку на тот же объект. Но когда объект разрушается, все другие указатели на адрес, ранее занятый теперь удаленным объектом , больше не являются указателями на этот объект . Они хранят один и тот же адрес, но этот адрес больше не является адресом какого-либо объекта (на самом деле он вскоре может быть снова использован в качестве адреса другого объекта).

Это различие было бы более очевидным, если бы указатели в C ++ вели себя как слабые ссылки, т. Е. Как только объект был уничтожен, все существующие указатели на него были бы немедленно установлены на 0. (Такого рода вещи считаются слишком дорогими во время выполнения, чтобы навязывать их всем программам на C ++, и на самом деле невозможно сделать их полностью надежными.)

ОБНОВЛЕНИЕ : Читая это спустя девять лет, это юрист. Теперь я нахожу вашу оригинальную реакцию понятной. Запретить мутацию, но разрешить ее уничтожение явно проблематично. Подразумеваемый контракт константных указателей / ссылок состоит в том, что их существование будет действовать как блок уничтожения целевого объекта, a.k.a. автоматическая сборка мусора.

Обычное решение этой проблемы - использовать почти любой другой язык.

5 голосов
/ 16 апреля 2009

Конструкторы и деструкторы не должны рассматриваться как «методы». Это специальные конструкции, которые инициализируют и разрушают объект класса.

'указатель const' указывает, что состояние объекта не изменится, когда с ним будут выполняться операции, пока он жив.

4 голосов
/ 13 октября 2011

Мне не разрешено вызывать любые неконстантные функции-члены с помощью константного указателя.

Да, вы.

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

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

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

Вы спутали константный указатель на неконстантный объект с неконстантным указателем на константный объект.

Сказав это,

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

удаление также разрешено по причинам, уже указанным в других ответах здесь.

...