Могу ли я назначить 0 для shared_ptr? Зачем?
Я понял, что в GCC 4.7 реализованы следующие компиляции:
#include <memory>
int main() {
std::shared_ptr<int> p;
p = 0;
}
Однако нет оператора присваивания из int
или из int*
, и нет никакого неявного конструктора из int
или int*
. Существует конструктор из int*
, но этот явно. Я проверил стандартную реализацию библиотеки, и конструктор действительно явный, и никаких подозрительных операторов присваивания не видно.
Является ли программа действительно хорошо сформированной или GCC возится со мной?
Ответы
Ответ 1
Причиной этого является короткая цитата из стандарта:
§4.10 [conv.ptr] p1
Константа нулевого указателя - это выражение integer constant (5.19) prvalue целочисленного типа , которое оценивается до нуля или prvalue типа std::nullptr_t
. [...] Константа нулевого указателя интегрального типа может быть преобразована в prvalue типа std::nullptr_t
. [...]
И тот факт, что std::shared_ptr
имеет неявный конструктор из std::nullptr_t
:
§20.7.2.2 [util.smartptr.shared] p1
constexpr shared_ptr(nullptr_t) : shared_ptr() { }
Это также допускает такие странности:
#include <memory>
void f(std::shared_ptr<int>){}
int main(){
f(42 - 42);
}
Пример в реальном времени.
Ответ 2
Вы можете назначить общий указатель другому экземпляру общего указателя. Назначение типа, которым владеет shared_pointer, невозможно. Afaik это единственная перегрузка для оператора:
shared_ptr& operator=(const shared_ptr& r);
То, что вы делаете, это присвоение указателю 0 (которое в этом случае равно NULL), а не значение типа. В этот момент кода вы не инициализированы.