Подтвердить что ты не робот

Является ли хорошей практикой освобождать память через указатель на константу

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

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

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

#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
};

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

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

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

Ответ 3

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

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

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

{
    Foo const x;
    ...
}

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

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

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

Ответ 4

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

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