В одном случае shared_ptr вызывает ошибку во время выполнения, в другом - нет - PullRequest
0 голосов
/ 05 марта 2019

Почему

struct X{};

X x;
X *q = &x;
std::shared_ptr<X> p(&x);

вызывает ошибку, а

X x;
X *q = &x;
std::shared_ptr<X> p0 = std::make_shared<X>(x);

не вызывает ошибку во время выполнения?

Я прочитал, что в первом случае у меня "два разныхуказатели, указывающие на одни и те же данные, и один из них является общим "

Но я думаю, что во втором случае такая же ситуация?

ошибка времени выполнения

free(): invalid pointer

Ответы [ 2 ]

0 голосов
/ 05 марта 2019

В первом случае объект 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);.

0 голосов
/ 05 марта 2019

В первом случае p становится владельцем x.Когда p выходит из области видимости, он удаляет x.Но x не был выделен динамически.Упс.

У вас нет такой ситуации во втором случае.Функция make_shared динамически распределяет новый общий объект.Когда p0 выходит из области видимости, он уничтожает этот вновь созданный объект.Обратите внимание, что в этом случае *p0 - это не x, а новый объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...