Почему оператор new не вынужден принимать аргумент как "const size_t"? - PullRequest
2 голосов
/ 22 июля 2011

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

void* operator new (size_t size)
{
  // distort `size` to other value
  return malloc(size);
}

Зная, что вышеупомянутое не может быть четко определенным поведением для перегруженного new (скажем, если size уменьшается), Почему стандартные компиляторы не заставляют его делать void* operator new (const size_t);?

То же самое можно утверждать и для operator delete, где он должен void operator delete (void* const); (добавляя const кизбегать изменения указателя).

Ответы [ 5 ]

8 голосов
/ 22 июля 2011
void* operator new (const size_t n);
void* operator new (size_t n);

Эти два полностью идентичных объявления operator new.Единственное отличие состоит в том, что если бы это было определение, n было бы или не будет разрешено изменять внутри тела функции (что не имеет значения для вызывающей стороны, поскольку параметр передается по значению).Поскольку это - деталь реализации, стандарт не говорит об этом.

Помните, константы верхнего уровня игнорируются в объявлениях функций.Они актуальны только в определениях.

6 голосов
/ 22 июля 2011

Тип аргумента в обоих случаях, const std::size_t и обычный std::size_t, равен std::size_t.Стандарт предписывает, что при обработке сигнатуры функции в объявлении (позже в определениях), const удаляется из типа.Конкретный абзац содержится в §8.3.5 / 3:

[...] После составления списка типов параметров для этих типов функций выполняется несколько преобразований для определения типа функции.Любой cv-квалификатор, модифицирующий тип параметра, удаляется.[Пример: тип void () (const int) становится void () (int) - конечный пример]

Теперь, в определении функции, const действительно имеет эффект, чтоВы предлагаете: заблокировать вас от изменения аргумента.Вы можете реализовать свой operator new с аргументом const std::size_t.С другой стороны, навязывать это было бы бесполезно.Как уже упоминали другие, тот факт, что аргумент является константным, может быть подорван путем копирования его в другую переменную и использования этой переменной.Нет смысла добавлять дополнительную нагрузку проверки к компиляторам, если это не добавляет реальной ценности языку.

2 голосов
/ 22 июля 2011

Хорошо, давайте представим, что это const:

void* operator new (const size_t size)
{
   size_t alteredSize = size;
   alteredSize += 10; // for whatever reason
   return malloc( alteredSize );
}

, что полностью совпадает с

void* operator new (size_t size)
{
   size += 10;
   return malloc( size );
}

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

2 голосов
/ 22 июля 2011

Константность для нереферентных аргументов имеет лишь незначительное значение.

Стандарты определяют "важные" вещи с точки зрения вызывающей стороны .

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

Обновление: Вы можете написать это таким образом, если хотите.

int f (const int);
int f (int) {return 0;}

int main () {
    int i;
    f (i);
}

Я не получил никаких ошибок с вышеупомянутым,Продолжайте и установите свой size_t: -)

Чтобы предвидеть возражение: здесь f заменяет operator new или что-то еще.Таким образом, у нас есть противоречивое объявление / определение, но компилятор не жалуется.Зачем?Потому что это просто не имеет значения.

1 голос
/ 22 июля 2011

Вы уже получили много хороших ответов на operator new.Еще один аргумент для , а не , делающий аргумент size равным operator new const: Переопределяющая реализация может захотеть выделить больше места, чем было запрошено, например, для файлов cookie, защитных слов и т. Д.

То же самое можно утверждать и для оператора delete, где он должен аннулировать оператор delete (void * const);(добавление const, чтобы избежать изменения указателя).

В большинстве современных операционных систем, использующих виртуальную память, free не обязательно освобождает выделенную память для ОС.Эта память все еще может находиться в виртуальном пространстве программы.Педантичный переопределитель вполне может захотеть заполнить указанную память абсолютным мусором перед его удалением, чтобы далее лишить законной силы последующее использование этой памяти вызывающей функцией.Вызывающая функция не должна использовать указанную память после ее удаления, так почему хоббл operator delete с ненужным ограничением?

...