ОК, так что сначала некоторые вещи, которые могут иметь значение:
Я использую компилятор Clang 3.1 в режиме С++ 11, а стандартная библиотека установлена на libС++.
Я пытаюсь ознакомиться с С++ 11, и при этом я сталкивался с поведением, которое кажется странным. Это может быть причуда Clang или libС++, но я не могу говорить на С++ standardese, и у меня нет доступа к другим компиляторам с поддержкой С++ 11, поэтому я не могу это проверить, и я искал Интернет и переполнение стека в меру своих возможностей, не найдя ничего связанного... так вот мы идем:
При использовании shared_ptr/unique_ptr для реализации RAII для простого ресурса, кажется, что их поведение отличается от нулевых указателей при удалении. Я понимаю, что обычно не нужно удалять нулевой указатель, но я ожидал, что поведение будет по крайней мере совпадать между двумя умными указателями STL.
В конкретном случае рассмотрим следующий код:
{
auto Deleter = [](void *){cout << "It later!" << endl;};
shared_ptr<void> spDoSomethingLater(nullptr, Deleter);
unique_ptr<void, void (*)(void *)> upDoSomethingLater(nullptr, Deleter);
cout << "It now!" << endl;
}
Я ожидал один из следующих выходов из этого:
a) Если оба имени вызываются, хотя указатель имеет значение null:
"It now!"
"It later!"
"It later!"
b) Если ни один из операторов не вызван, поскольку указатель имеет значение null:
"It now!"
Но я не наблюдаю ни одного из этих случаев. Вместо этого я наблюдаю:
"It now!"
"It later!"
Это означает, что вызывается один, но не другой из удалений. При дальнейшем исследовании я обнаружил, что делеттер для shared_ptr вызывается независимо от того, содержит ли он нулевое значение, но деблокирование unique_ptr вызывается только в том случае, если оно не содержит нулевого значения.
Мои вопросы: Это действительно правильное поведение, указанное стандартом? Если да, то почему указанное поведение отличается друг от друга двумя типами STL таким образом? Если нет, это ошибка, которую я должен сообщить libС++?