Почему delete может выполнять указатели на const, а free - нет? - PullRequest
11 голосов
/ 06 августа 2011

Я только что заметил, что указатели, переданные на delete, могут быть квалифицированы const, а указатели, переданные на free, - нет. Это действительно сюрприз для меня.

А в C ++ перегрузка на operator delete должна иметь такую ​​подпись:

void operator delete(void* p);

Но добавление const к указателю параметра недопустимо:

void operator delete(void const* p);

Может кто-нибудь сказать мне, почему delete разработан таким образом?

Ответы [ 4 ]

18 голосов
/ 06 августа 2011

free не должен использоваться с реальными объектами C ++. free следует использовать с malloc, поэтому вы не должны использовать free для чего-то, что выделено с new.

Относительно того, почему вы можете delete const объекты, это просто:

const Type *ptr = new Type(...);

И что теперь? Если вы не можете это удалить, вам придется сделать следующее:

delete const_cast<Type*>(ptr);

Наличие объекта const означает, что его нельзя изменить. Вы не можете заставить объект перейти из одного состояния в другое. Удаление выбрасывает это. Это означает, что он больше не существует в любом состоянии, будь то оригинальная или какая-либо другая измененная форма. Удаление - это операция, которая существует вне состояния изменчивости объекта, очень похоже на конструкцию.

Концептуально удаление не является ни постоянным, ни неконстантным. В то время как деструктор является неконстантной функцией, идея разрушения объекта просто находится вне области констант или неконстант.


ОК, допустим, вы определили operator delete, чтобы взять указатель на const (который отличается от указателя const) :

void operator delete(void const* p);

Какой будет первая строка этой функции? Цель operator delete - освободить память, выделенную operator new. Это потребует тыкать в биты в куче выделения памяти. И для этого вам нужен указатель, который не указывает на постоянные данные:

void *ptr = const_cast<void*>(p);

Добро пожаловать в неопределенное поведение . Хотя C ++ позволяет вам делать это, в спецификации совершенно ясно, что результаты попытки записи в ptr (или любой адрес на его основе) равны undefined . Вам дали указатель const; внешний мир сказал вам не изменять то, на что он указывает. C ++ не дает никаких гарантий относительно того, что произойдет, когда вы нарушите этот контракт.

Поскольку в спецификации указано, что это неопределенное поведение, и поскольку operator delete (в большинстве случаев) не может выполнить свою работу без , не изменив память, на которую указывает p (или не изменив память на основе этого адрес), было бы глупо из спецификации, чтобы затем позволить вам определить operator delete таким образом. Это было бы в основном канонизацией идеи стрелять себе в ногу.

Да, практически в каждом случае это было бы абсолютно безопасно. Но так как вы все равно собираетесь отбросить константу, зачем вообще пытаться разрешить довольно сомнительную идею?

6 голосов
/ 07 августа 2011

free - это функция C.Его подпись 20-30 лет, со времен, когда не было const на языке C (и также не было языка C ++).Компилятор C ++ обрабатывает free, как и любую другую функцию, и не может позволить ему принимать указатель const без преобразования, потому что free может изменить указанный объект.На самом деле это так же, как и delete, но C ++ не знает, что free используется для управления памятью.

2 голосов
/ 06 августа 2011

Одно отличие состоит в том, что free является библиотечной функцией, и вы должны соответствовать типу параметра. Когда free был добавлен к языку C, не было ключевого слова const, так что это даже нельзя было рассмотреть.

В C ++ delete p - это оператор, обрабатываемый компилятором. Он может делать все, что хочет разработчик языка, в том числе не учитывать, является ли указанный объект const или нет.

С философской точки зрения, оператор delete не изменяет объект, он просто убирает его.

2 голосов
/ 06 августа 2011

Модификатор const, примененный к указателю, означает, что указанный объект не будет изменен.

Однако delete выводит объект из обращения навсегда. Никому не нужно заботиться о том, что происходит с ним после его удаления Следовательно, насколько мы знаем, удаление может изменить объект или нет. Почему это имеет значение? Любая попытка чтения или записи содержимого объекта будет неопределенным поведением.

С другой стороны, когда вы реализуете свой собственный delete, вам, вероятно, потребуется изменить умирающий объект. Следовательно, указатель должен быть неконстантным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...