Удаление указателя на const (T const *)

89

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

delete p;

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

delete this;

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

Naveen
источник

Ответы:

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

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

Агнель Куриан
источник
21
+1 за последнее изменение. Думаю, это верная причина. Автоматический вызов деструктора для объекта const - почти то же, что и delete f; где f - указатель на const.
bayda
const Foo * fили Foo const * fне является константным указателем на Foo. Это указатель на const Foo. Foo * const f константный указатель на Foo.
user11373693
48

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

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

Пол Дж. Уильямс
источник
3
Деструкторы могут мутировать объекты довольно жестокими способами, так что это должно быть какое-то странное использование слова «неизменный», о котором я раньше не знал ...
DarthGizka
1
@DarthGizka нет, деструкторы переводят вас из состояния, в котором есть объект, в состояние, в котором его нет. C ++ не определяет какой-либо метод для наблюдения за "мутацией" после уничтожения
Калет
@ Caleth: стандарт может не разрешать вам смотреть на объект после того, как его деструктор завершился, но вам, безусловно, разрешено смотреть на побочные эффекты, вызванные разрушением. Следовательно, можно легко организовать обстоятельства, чтобы сделать изменение «неизменяемого» объекта наблюдаемым. В США за убийство трудно привлечь к уголовной ответственности, когда нет тела, но это все равно убийство (и могут быть другие доказательства, достаточные для вынесения обвинительного приговора). Такая же разница.
DarthGizka
6

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

Да Вы.

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

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

Окталист
источник
5

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

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

Indy9000
источник
5

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

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

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

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

Дэниел Эрвикер
источник
Если вы не можете уничтожить то, на что указывают указатели на const, как вы справитесь с std::unique_ptr<const T>концом его жизни?
Калет
@Caleth, тогда на C ++ не будет решения этой проблемы. Это всего лишь один пример общей проблемы: в C ++ модификатор const означает «Вы не можете изменить цель, за исключением одного смысла, когда вы можете полностью разрушить ее и сделать все другие ссылки на нее недействительными и источники неопределенного поведения». Вот почему я думаю, что этот тип вопросов должен побуждать к рассмотрению других языков. В нем есть UB-дыры, которые нельзя решить без использования другого базового подхода.
Дэниел Эрвикер,