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

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

delete p;

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

delete this;

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


person Naveen    schedule 16.04.2009    source источник


Ответы (5)


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

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

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

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

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

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

person PaulJWilliams    schedule 16.04.2009
comment
Деструкторы могут мутировать объекты довольно жесткими способами, так что это должно быть какое-то странное использование слова «неизменный», о котором я раньше не знал ... - person DarthGizka; 15.05.2016
comment
@DarthGizka нет, деструкторы переводят вас из состояния, в котором есть объект, в состояние, в котором его нет. C ++ не определяет никаких методов для наблюдения за уничтожением пост-мутации. - person Caleth; 27.09.2018
comment
@ Caleth: стандарт может не разрешать вам смотреть на объект после того, как его деструктор завершился, но вам, безусловно, разрешено смотреть на побочные эффекты, вызванные разрушением. Следовательно, можно легко устроить обстоятельства, чтобы сделать изменение «неизменяемого» объекта наблюдаемым. В США за убийство трудно привлечь к уголовной ответственности, когда нет тела, но это все равно убийство (и могут быть другие доказательства, достаточные для вынесения обвинительного приговора). Такая же разница. - person DarthGizka; 27.09.2018

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

Да, вы.

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

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

person Oktalist    schedule 13.10.2011

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

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

person Indy9000    schedule 16.04.2009

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

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

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

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

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