В связи с чем возникают вопросы. А что будет вот с таким кодом? Будет ли вызван деструктор при выходе из блока?
{
const CMyClass p;
}
А вот это как же? Скомпилируется?
{
const int* p = new int(10);
delete p;
}
На самом деле всё здесь нормально и всё компилируется и работает. Потому что для деструктора сделано исключение и его можно звать для константных объектов.
Об этом лучше помнить, чтобы потом не писать вот так:
delete const_cast<ReferenceCounter*>(this);
Куски из Стандарта по теме:
[class.dtor] 12.4/2:
A destructor is used to destroy objects of its class type. A
destructor takes no parameters, and no return type can be specified
for it (not even void). The address of a destructor shall not be
taken. A destructor shall not be static. A destructor can be invoked
for a const, volatile or const volatile object. A destructor shall
not be declared const, volatile or const volatile (9.3.2). const and
volatile semantics (7.1.5.1) are not applied on an object under
destruction. Such semantics stop being into effect once the destructor for the most derived object (1.8) starts.
[expr.delete] 5.3.5/2:
[Note: a pointer to a const type can be the operand of a
delete-expression; it is not necessary to cast away the
constness (5.2.11) of the pointer expression before it
is used as the operand of the delete-expression. ]
Ссылки по теме:
comp.lang.c++.moderated - Delete a const pointer?
comp.lang.c++.moderated - Why can operator delete be called on a const pointer?
Интересный факт насчет деструктора. Вобщем-то я и раньше так писал, но не думал, что есть отдельный пункт в стандарте. Спасибо!
ОтветитьУдалить>> Конструктор, кстати, тоже нельзя.
Конструктор, строго говоря, вообще не метод класса - скорее, статический метод, ведь он вызывается когда объект еще не существует.
Ну тут конечно все достаточно очевидно. Было бы странно, если бы было как-нибудь по-другому.
ОтветитьУдалитьНапример, что бы значил спецификатор const у конструктора или деструктора? Наверняка не то же самое, что и у обычной функции.
Но тем не менее, спасибо. Иногда бывает полезно задуматься и над очевидными вещами :)
Еще бы сто лет писал delete p для константного объекта и не задумывался бы, если б не прочитал :( Наверное, пора начинать покуривать стандарт перед сном.
ОтветитьУдалитьСпасибо большое! Интерсная штука)
ОтветитьУдалитькстати интересна в этой связи парадигма уничтожающей функции,
ОтветитьУдалитьнапример Release(), в этом случае константность указателя на объект будет также означать невозможность удаления такого объекта.
Ну, собственно, именно для таких случаев и придумали const_cast… Хотя ситуация, когда объект должен удаляться кем-то, кто имеет к нему доступ только по константному указателю, это огрехи в проектировании.
ОтветитьУдалитьимел в виду, что это можно использовать в каких-нибудь полезных целях :)
ОтветитьУдалить
ОтветитьУдалить>> Хотя ситуация, когда объект должен удаляться кем-то, кто имеет к нему доступ только по константному указателю, это огрехи в проектировании.
Это не огрехи проектирования, а умные указатели...
Это отдельный случай
ОтветитьУдалитьCпасибо - интересный пост! Интересные факты, порадовали!
ОтветитьУдалитьОпечатка в первом абзаце.
ОтветитьУдалитьДекструктор вместо деструктор
вероятно лучше как-то так
ОтветитьУдалитьdelete[] p;
delete[] p;
ОтветитьУдалитьстоило бы писать если б создавался масив интов:
const int* p = new int[10];
в примере создается только один инт и инициализируется значением 10;
const int* p = new int(10);
так что все правильно.