2014-02-06 2 views
5

Я читал о умных указателях C++ 11, чтобы использовать их в своих источниках, документация, которую я читал, является той, что на cppreference.com; читая о std::unique_ptr, на reset function есть документация, которая кажется неправильным мне (курсив мой):std :: unique_ptr :: reset проверяет недействительность управляемого указателя?

Заменяет управляемый объект.

  • Учитывая current_ptr указатель, который управляет *this, выполняет следующие действия в указанном порядке:

    1. Сохраняет копию текущего указателя old_ptr = current_ptr.
    2. Заменяет текущий указатель аргументом current_ptr = ptr.
    3. Если старый указатель не был пустым, удаляет ранее управляемый объект if(old_ptr != nullptr) get_deleter()(old_ptr).

В стандартной документации C++, мы можем прочитать известную удалить нулевую функцию указателя:

Выписка из n3690 стандарта 5.3.5 Удаление (курсив мой):

Если значение операнда delete-expression не является нулевым значением указателя, то:

- Если вызов выделения для нового выражения для объекта, подлежащего удалению, не был пропущен, delete-expression должен вызвать функцию освобождения. Значение, возвращаемое из вызова выделения нового выражения, передается как первый аргумент функции освобождения.

- В противном случае удаления выражение не будет вызывать функцию Deallocation.

Итак, я задаюсь вопрос, почему cppreference говорит, что unique_ptr::reset функция проверяет ничтожность управляемого указателя, прежде чем это удаление даже в то время как тот стандарт говорит, что ни одна функция открепления не будет называться по нулевому указателю (именно поэтому Документация cppreference кажется мне неправильной).

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

PS: Где в стандарте определено, как должно осуществляться или вести себя как std::unique_ptr? В 20.9.1 Шаблон класса unique_ptr Я ничего не могу найти о check-for-nullity.

+3

'delete' - это не единственное, что сделано для того, чтобы избавиться от указательного ресурса. У вас может быть пользовательский deleter, который 'free' или другие вещи, которые не любят нулевые указатели. – Xeo

ответ

6

Да, проверка на непустой требуется стандарт (C++ 11, [unique.ptr.single.modifiers]§4):

void reset(pointer p = pointer()) noexcept; 

4 Эффектов: присваивает p сохраненного указатель, а затем если старое значение сохраненного указателя, old_p, не было равно nullptr, звонки get_deleter()(old_p). [Примечание: Порядок этих операций значителен, поскольку вызов get_deleter() может уничтожить *this. -end примечание]

(курсив мой)

Обсуждение: Альтернативный способ стандартизации было бы поставить «бремя» на пользователя класса, т.е. требуют, чтобы все удаливших (по умолчанию один и любые пользовательские), чтобы нормально работать при вызове с помощью нулевого указателя.

Однако я понимаю, что идея заключалась в том, чтобы включить такие функции, как free(), и даже такие вещи, как гипотетический unlock_mutex(Mutex*), работать как удаленные из коробки, независимо от того, как они обрабатывают нулевые указатели. Поэтому, ставя эту проверку в unique_ptr, она расширяет выбор удалений, которые могут быть использованы напрямую.

+0

И что может быть причиной этого, если удаление нулевого указателя не имеет эффекта? –

+3

@PaperBirdMaster Что делать, если дебелтор не является дефолтом по умолчанию и не работает с нулевым указателем? – Angew

+0

Ну, я предполагал, что если вы создадите пользовательский делетер, этот пользовательский деактивирующий ** должен ** соответствовать некоторым условиям вроде *, не пытайтесь работать над нулевым указателем *, но, очевидно, это была моя ошибка (и я не могу найти ничего об условиях/preconditios об пользовательском делетере, так что это должно быть причиной :) –

2

Что делать, если ваш предприниматель не выполняет операцию простого удаления? Что, если ваш unique_ptr имеет пользовательский удаляющий элемент, который делает что-то еще, вы бы хотели, чтобы ваш делетер был вызван с помощью nullptr в качестве параметра? : D

+0

Если я когда-либо хотел, чтобы мой пользовательский делегат вызывался с нулевым указателем: я проверю недействительность на сам делектор: P, но теперь я могу предположить, что мой пользовательский деаетер не будет вызываться с помощью «nullptr» (даже если бы я хотел, по какой-то случайной и бесполезной причине) –

+1

@PaperBirdMaster На самом деле оператор 'delete', проверяющий нулевой указатель, является странным парнем на языке, где вы не должен заплатить за то, что вы не используете (зачем мне платить за дополнительную проверку, если я никогда не удалю 'nullptr'?), но я думаю по историческим причинам и для имитации поведения' free() 'это было сделанный для проверки на 'nullptr', поскольку достаточное количество кодеров, похоже, полагается на это поведение. Тот же пользовательский дебетер, который вы используете, может также использоваться в другом контексте, где проверка на 'nullptr' не имеет большого смысла, было бы грустно требовать обертку только для нулевой проверки :) – Drax

Смежные вопросы