Чи здатні 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.