четверг, 5 декабря 2013 г.

[prog.c++] Почему можно вызывать delete для указателя на const-объект?

До вчерашнего дня был убежден, что язык не разрешает вызывать delete для указателя на const-объект. Оказалось, что ошибался. Вот такая программа успешно компилируется и запускается:

class A {};

void bar( const A * p ) { delete p; }

int main() {
   bar( new A() );
}

Кто-нибудь может объяснить, почему это возможно? Upd. Спасибо, объяснение получено, см. ниже.

Лично я очень удивлен по двум причинам:

Во-первых, указатель на const-объект, это read-only view на объект. И когда посредством read-only view объект уничтожается вообще, то это, по меньшей мере, неожиданно.

Во-вторых, через указатель на const-объект компилятор позволяет вызывать только const-методы объекта. Но деструктор не является таким методом с формальной точки зрения.

Соответственно, я не припомню, чтобы видел где-то в "дикой природе" уничтожение объекта через указатель на const. Если кто-то из читателей видел, то подскажите, где на это можно посмотреть, пожалуйста.


А вот и ответ на мой вопрос на stackoverflow.

Это необходимо, чтобы можно было делать так:

void foo()
{
   const A * p = new const A();

   delete p;
}

В принципе, вещь для меня неожиданная. Это если говорить о конкретных типах. Но вот если речь заходит о шаблонах, тогда все становится на свои места.

templateclass T >
void some_common_action()
{
   T * p = new T();
   // do something...
   delete p;
}

Здесь в качестве T для some_common_action может быть как просто A, так и const A. Причем тип аргумента при обращении к some_common_action может выводиться в каком-то другом, возможно совсем нетривиальном шаблоне. Поэтому для шаблонов возможность применения delete к указателю на const выглядит разумной.

Другое дело, что теперь нужно внимательнее относиться к функциям, которые в качестве аргумента принимают const T *. Вдруг ее разработчику взбредет в голову вызвать delete для аргумента. А я ни сном, ни духом :)

Комментариев нет: