C ++ 11 unique_ptr ve shared_ptr birbirlerinin türüne dönüşebilir mi?


108

Mu C ++ 11 standart kütüphane bir dönüştürmek için herhangi bir fayda temin std::shared_ptretmek std::unique_ptr, ya da tam tersi? Bu güvenli işlem mi?


Lütfen "güvenli çalışmayı" tanımlayın. Ne tür bir güvenlik arıyorsunuz? ömür boyu yönetim güvenliği? İplik güvenliği?
pürüzlüSpire

2
"STL", standart kitaplık anlamına gelmez. STL'nin hiçbir ilgisi yok shared_ptr.
Meraklıguy

1
@jaggedSpire İplik güvenliği, sahiplerin farklı iş parçacıklarında kullandığı anlamına gelir, yani kullanım sayısı 1 değildir.
wonderguy

@curiousguy bunu biliyordum. Demek istediğim, OP'nin sorusunda "güvenlik" iyi tanımlanmamıştı ve birden fazla tür olduğu için ne tür "güvenlik" i kastettiğini netleştirmesi gerekiyordu.
jaggedSpire

Yanıtlar:


174

std::unique_ptrözel mülkiyeti ifade etmenin C ++ 11 yoludur, ancak en çekici özelliklerinden biri, kolayca ve verimli bir şekilde std::shared_ptr.

Bu, std::unique_ptrfabrika işlevi dönüş türü olarak neden bu kadar uygun olduğunun önemli bir parçasıdır . Fabrika işlevleri, arayanların geri döndükleri nesne için özel sahiplik semantiğini kullanmak isteyip istemediklerini veya paylaşılan sahipliğin (yani std::shared_ptr) daha uygun olup olmayacağını bilemez . std::unique_ptrFabrikalar, bir geri göndererek arayanlara en verimli akıllı işaretçiyi sağlar, ancak arayanların onu daha esnek kardeşiyle değiştirmesini engellemezler.

std::shared_ptriçin std::unique_ptrizin verilmez. Bir kaynağın yaşam boyu yönetimini bir kaynağa std::shared_ptrdönüştürdüğünüzde, fikrinizi değiştirmezsiniz. Referans sayısı bir olsa bile, örneğin bir yönetime sahip olmak için kaynağın sahipliğini geri alamazsınız std::unique_ptr.

Referans: Etkili Modern C ++. 42 C ++ 11 VE C ++ 14 KULLANIMINIZI GELİŞTİRMENİN ÖZEL YOLLARI. Scott Meyers.

Kısacası, kolayca ve verimli bir şekilde dönüştürebilir std::unique_ptriçin std::shared_ptrancak dönüştürmek olamaz std::shared_ptriçin std::unique_ptr.

Örneğin:

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

veya:

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

10
...Bunu nasıl yapıyorsun?
Jake

4
@Jake Bir örnek ekledim
chema989

İzin verilmez iken derleyici (en azından değil gcc) aslında farkında olun değil yanlışlıkla (örneğin üye değişkenin işaretçi türünü değiştirerek) bir atarsanız önlemek (veya hatta uyar) std::unique_ptra std::shared_ptr.
StefanQ


@StefanQ Bir std::unique_ptriçine a atamasına izin verilmediğini düşündüren nedir std::shared_ptr? Standart kütüphane bir hareket atama operatörü tanımlar template<class Y, class Deleter> shared_ptr& operator=(std::unique_ptr<Y, Deleter>&& r); için std::shared_ptr<T>.
cuddlebugCuller

-8

Unique_ptr u_ptr verildiğinde, shared_ptr s_ptr oluşturun:

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

Diğer tarafa gitmek pratik değildir.


30
İşte "doğru" yol:std::shared_ptr<whatever> s_ptr(std::move(u_ptr));
emlai

7
Ve işte std::shared_ptr<whatever> s_ptr{std::move(u_ptr)};
bilgiççe

3
Bununla ilgili daha az güvenli olan ne?
nmr

7
@VioletGiraffe • Sanırım polyvertex, sessiz daraltma dönüşümlerini önleyen ve tek tip bir sözdizimiyle üye başlatmayı barındıran yeni başlatma listesi sözdizimini kullanmayı iyi bir alışkanlık olarak savunuyor. Birinden altı, diğerinden yarım düzine mi?
Eljay

10
@nmr Güvensiz çünkü Deleteriçinde depolananları kaybedebilirsinizunique_ptr
Zang MingJie
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.