Это хорошая практика, чтобы освободить память с помощью указателя на const - PullRequest
10 голосов
/ 18 февраля 2010

Существует множество вопросов, в которых обсуждаются детали C и C ++, связанные с удалением указателя на const, а именно, что free() не принимает их и что delete и delete[] делают, и что constness не мешает объекту уничтожение.

Меня интересует, считаете ли вы, что это хорошая практика, а не то, что допускают языки (C и C ++).

Аргументы для удаления указателя на const включают в себя:

  • Линус Торвальдс kfree(), в отличие от C free(), принимает аргумент void const*, потому что считает, что освобождение памяти не влияет на то, на что он указывает.
  • free() был разработан до введения ключевого слова const.
  • Операторы удаления в C ++ позволяют удалять постоянные данные.

Аргументы против этого включают:

  • Программисты не ожидают, что данные будут изменены (или удалены), когда они передают указатель на константу.
  • Многие думают, что указатель на const подразумевает отсутствие прав владения данными (но не то, что non-const подразумевает получение прав владения).
  • Это обычная практика, наблюдаемая в большинстве библиотек и существующего кода.

Пожалуйста, аргументируйте в своих ответах и, возможно, обращайтесь к властям. Я не собираюсь проводить здесь опрос.

Ответы [ 4 ]

4 голосов
/ 18 февраля 2010

Хорошей практикой является использование правильной стратегии для окончания срока службы объекта. Для динамических объектов это означает, что вы удалите новое, освободите то, что вы используете, и так далее. Является ли этот объект постоянным или нет, не влияет на то, должен ли закончиться срок его жизни.

Быть постоянным или изменчивым - это свойства, которые существуют в течение времени жизни объекта и заканчиваются выражением удаления или вызовом free. Независимо от ваших собственных взглядов на вопрос или того, как все работает на других языках, именно так работает объектная модель C ++. Простой пример, демонстрирующий, как язык переводит выражения delete в вызовы оператора delete:

#include <new>
void* operator new(std::size_t size);
void operator delete(void* p);

int main() {
  delete new int(); // int* to void*, since this is also an allowed
  // implicit conversion, it may not be clear what is happening

  // however, these are clearly not implicit conversions:
  delete new int const();          // int const         * to void*
  delete new int volatile();       // int       volatile* to void*
  delete new int const volatile(); // int const volatile* to void*
}

Другой пример, но, возможно, менее понятный, заключается в том, почему вы не можете перегрузить ctors для const:

struct S {
  S() const; // not allowed
};

Объект является константным только после того, как он создан (иначе его время жизни начинается; происходит, когда ctor возвращается нормально) и до того, как он уничтожается (иначе его время жизни заканчивается; происходит, когда вводится dtor). До или после этого времени жизни у вас может быть указатель типа T const* (например), но он не указывает на объект и разыменовывает его как UB.

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

(Я полагаю, что этот вопрос субъективен и аргументирован * и проголосовал бы за его закрытие таким образом, за исключением того, что я, очевидно, помог зажечь дискуссию; поэтому ответил как CW.)

3 голосов
/ 18 февраля 2010

Я никогда не понимал аргументов против удаления (или освобождения) константного указателя. Точнее, я в некоторой степени вижу рациональное, но мне кажется, что они одинаково хорошо применимы к элементу const в объекте или переменной const в блоке, и я никогда не видел, чтобы кто-либо утверждал, что они не должны быть уничтожены и их память освобождается, когда содержащий объект удаляется или выполнение покидает содержащий его блок.

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

Другими словами, если

{
    Foo const x;
    ...
}

это действительный и хороший стиль. Почему бы

{
    Foo const* xptr = new Foo;
    ...
    delete xptr;
}

не будет хорошим стилем (использование адекватного умного указателя вместо сырого, но это другая проблема).

2 голосов
/ 18 февраля 2010

Ну, вот некоторые важные вещи, возможно, слишком длинные, чтобы вписаться в комментарий:

  1. Некоторое время назад практика освобождения памяти через указатель на константу была просто запрещена, см. это др.Статья Добба, «Закон о языке» (:)), часть .

  2. Дважды обсуждалась тема http://groups.google.ru/group/comp.lang.c++.moderated: «Удалить константный указатель?» , «Почему оператор удаления может быть вызван для константного указателя» (оба фактически имеют дело с рассматриваемым случаем,т.е. указатель на const).

  3. Моя собственная точка зрения (поскольку вы запрашиваете аргументы): возможность рассматриваемой операции в любом заданном контексте определяется (явно или неявно определенным вдокументация) контракт класса или функции, а не только сигнатура метода или типы параметров.

0 голосов
/ 18 февраля 2010

Constness и продолжительность жизни - две разные вещи. Я не вижу проблем с освобождением объекта const, если владелец этого объекта решает, что у объекта нет причин жить (так же, как локальный объект const будет «освобожден», когда он выйдет из области видимости).

Поскольку free() не принимает указатель const, я думаю, что можно утверждать, что это могло быть упущением комитета по стандартам или потому, что оно принимает тот же вид, если указатель malloc() возвращается.

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