Чи здатні C ++ 11 унікальні_ptr та shared_ptr перетворити на тип один одного?


99

Чи надає стандартна бібліотека C ++ 11 будь-яку утиліту для перетворення з а std::shared_ptrв std::unique_ptrабо навпаки? Це безпечна робота?


Визначте, будь ласка, "безпечну експлуатацію". Яку безпеку ви шукаєте? безпеку управління життям? Безпека нитки?
— зазубрений шпиль

2
"STL" не означає стандартну бібліотеку. STL не має нічого спільного shared_ptr.
— curiousguy

1
@jaggedSpire Тема безпеки означатиме, що у вас є власники, які використовуються в різних
— потоках

@curiousguy Я це знав. Моя думка полягала в тому, що "безпека" не була чітко визначена в питанні ОП, і йому потрібно було уточнити, який тип "безпеки" він має на увазі, оскільки існує кілька видів.
— jaggedSpire

Відповіді:


161

std::unique_ptrце спосіб С ++ 11 виразити ексклюзивне право власності, але однією з найпривабливіших його можливостей є те, що він легко і ефективно перетворюється на a std::shared_ptr.

Це ключова частина того, чому std::unique_ptrвін так добре підходить як тип повернення заводських функцій. Фабричні функції не можуть знати, чи бажаючі хочуть використовувати ексклюзивну семантику власності для об'єкта, який вони повертають, чи std::shared_ptrбільш доцільним буде спільне володіння (тобто ). Повертаючи a std::unique_ptr, фабрики надають абонентам найефективніший інтелектуальний покажчик, але вони не заважають абонентам замінити його на більш гнучкий брат.

std::shared_ptrдо std::unique_ptrзаборонено. Після того, як ви перетворили управління ресурсом на все життя на a std::shared_ptr, ви не передумаєте. Навіть якщо кількість посилань одна, ви не можете повернути право власності на ресурс, щоб, скажімо, мати право std::unique_ptrкерувати ним.

Довідка: Ефективний сучасний C ++. 42 КОНКРЕТНІ СПОСОБИ ПОЛІПШЕННЯ ВАШОГО ВИКОРИСТАННЯ С ++ 11 І С ++ 14. Скотт Майерс.

Коротше кажучи, ви можете легко і ефективно перетворити a std::unique_ptrна, std::shared_ptrале не можете перетворити std::shared_ptrна std::unique_ptr.

Наприклад:

std::unique_ptr<std::string> unique = std::make_unique<std::string>("test");
std::shared_ptr<std::string> shared = std::move(unique);

або:

std::shared_ptr<std::string> shared = std::make_unique<std::string>("test");

9
...Як ти це робиш?
— Джейк

4
@Jake Я додав приклад
— chema989

Майте на увазі, що, хоча це не дозволено, компілятор (принаймні не gcc) насправді не завадить (або навіть попередить), якщо ви випадково (наприклад, змінивши тип вказівника змінної члена) призначите std::unique_ptra std::shared_ptr.
— StefanQ

-8

Враховуючи унікальний_ptr u_ptr, створіть shared_ptr s_ptr:

std::shared_ptr<whatever> s_ptr(u_ptr.release());

Йти іншим шляхом недоцільно.


29
Ось "правильний" спосіб:std::shared_ptr<whatever> s_ptr(std::move(u_ptr));
— emlai

6
І ось педантичний "правильний" шлях:std::shared_ptr<whatever> s_ptr{std::move(u_ptr)};
— полівертекс

3
Що з цього менш безпечно?
— nmr

7
@VioletGiraffe • Я вважаю, що полівертекс виступає за використання нового синтаксису списку ініціалізації - який дозволяє уникнути мовчазного звуження перетворень та розміщення ініціалізації членів з рівномірним синтаксисом - як хороша звичка потрапляти. Шість одного, півдесятка іншого?
— Eljay

8
@nmr Це небезпечно, тому що ви можете втратити Deleterзбережене всерединіunique_ptr
— Zang MingJie
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.