В первом случае объект x
удаляется, хотя срок его службы уже заканчивается с окончанием его области действия.Здесь вы создаете экземпляр в стеке и в своей области видимости:
X x; // lifetime automatically ends at the end of the scope
Затем вы просите std::shared_ptr
также управлять временем жизни адреса x
.
std::shared_ptr<X> p(&x); // calls delete at the end of the scope
Следовательно, вы освобождаете одну и ту же переменную дважды, что является неопределенным поведением.Во втором случае вы создаете std::shared_ptr
для скопированного экземпляра, который не зависит от экземпляра x
.
std::shared_ptr<X> p0 = std::make_shared<X>(x); // Copies x, then deletes the copy
Это не проблема, поскольку оба объекта удаляются только один раз.
Обратите внимание на семантику std::make_shared
здесь: аргументы, которые вы ей передаете, передаются конструктору аргумента шаблона.Следовательно, вы запускаете сгенерированный компилятором конструктор копирования X(const X&)
.Это очень отличается от создания std::shared_ptr
из уже существующего указателя через std::shared_ptr p(&x);
.