SORU
3 Ocak 2014, Cuma


C make_shared ve normal shared_ptr farkı

std::shared_ptr<Object> p1 = std::make_shared<Object>("foo");
std::shared_ptr<Object> p2(new Object("foo"));

Google ve stackoverflow birçok mesaj var bu konuda, ama make_shared doğrudan shared_ptr kullanarak daha verimli olduğunu anlamak mümkün değilim.

Birisi açıklasın bana make_shared verimli nasıl anlamak mümkün olacak, böylece nesnelerin adım dizisi ve işlemleri her iki tarafından yapılan adım. Başvuru için yukarıda bir örnek verdim.

CEVAP
3 Ocak 2014, Cuma


Fark std::make_shared std::shared_ptr kurucu çağırmak iki gerçekleştirir ise bir yığın ayırma gerçekleştirir.

Nerede yığın ayırma olur mu?

std::shared_ptr iki varlık yönetir

  • denetim bloğu (ref-sayar gibi mağazalarda meta verileri sildim türü deleter, vb)
  • nesne yönetilen

std::make_shared denetim bloğu hem de veri alanı için gerekli yığın ayırma tek bir muhasebe yapar. Diğer durumda, new Obj("foo") çağırır bir yığın ayırma yönetilen veri ve std::shared_ptr yapıcı denetim bloğu için de bir tane yapar.

Daha fazla bilgi için, check outUygulama Notlarıcppreference.

Güncelleme: Durum-Güvenlik

OP şeyler hariç-güvenlik tarafı merak gibi görünüyor beri, ben cevabımı güncelledik.

Bu örneği ele alalım

void F(const std::shared_ptr<Lhs> &lhs, const std::shared_ptr<Rhs> &rhs) { /* ... */ }

F(std::shared_ptr<Lhs>(new Lhs("foo")),
  std::shared_ptr<Rhs>(new Rhs("bar")));

C iç ifadelerin değerlendirilmesi keyfi sipariş verir, çünkü, olası bir sipariş

  1. new Lhs("foo"))
  2. new Rhs("bar"))
  3. std::shared_ptr<Lhs>
  4. std::shared_ptr<Rhs>

Şimdi, bir istisna adım 2 (örn. atılan etsek bellek istisna, Rhs yapıcı bazı özel durum gönderdi). Biz o zaman hafıza 1, hiçbir şey beri bunu temizlemek için bir şansa sahip olacaktır adımda tahsis kaybedersiniz. Sorunun esası burada ham işaretçi std::shared_ptr kurucusuna hemen geçti alamadım.

Bunu düzeltmek için tek yol bu keyfi sipariş gerçekleştirilemiyor böylece ayrı satırlarda bunları yapmak için.

auto lhs = std::shared_ptr<Lhs>(new Lhs("foo"));
auto rhs = std::shared_ptr<Rhs>(new Rhs("bar"));
F(lhs, rhs);

Tabii ki bunu çözmek için tercih edilen yolu std::make_shared yerine kullanmaktır.

F(std::make_shared<Lhs>("foo"), std::make_shared<Rhs>("bar"));

Güncelleme II: std::make_shared Dezavantajı

Casey'in sözleri: . alıntı

Tek bir ayırma var bu yana, pointee belleği kontrol bloğu artık kullanımda kadar kaldırıldı edilemez. weak_ptr bir denetim bloğu kadar hayatta kalabilir.

Neden weak_ptrs örneklerini kontrol bloğu canlı tutmak mı?

weak_ptrler için bir şekilde yönetilen nesne hala geçerli olup olmadığını belirlemek için (örn. olmalı lock). Kontrol bloğunda saklanan ve yönetilen nesne, kendi shared_ptrs sayısını kontrol ederek bunu yapıyorlar. Sonucu kontrol blokları shared_ptr sayısı kadar canlı ve weak_ptr sayısı 0 hit hem de.

std::make_shared geri

std::make_shared tek bir kontrol bloğu ve yönetilen nesne için tahsisat yığın yapar, kontrol bloğu için bellek boşaltmak ve yönetilen bağımsız bir nesne yoktur. shared_ptrs weak_ptrs hayatta hiçbir kadar kontrol bloğu ve olur yönetilen nesne, her ikisi de özgür olana kadar beklemeliyiz.

Sanırım biz yerine yığın ayırma denetim bloğu için iki gerçekleştirilen ve new shared_ptr ile yönetilen nesne oluşturucu. O zaman biz boş bellek için yönetilen nesne (belki daha erken) yok shared_ptrs hayatta ve boş bellek için kontrol bloğu (belki daha sonra) yok weak_ptrs hayatta.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • calicoJake

    calicoJake

    29 EKİM 2007
  • Jeb Corliss

    Jeb Corliss

    17 Kasım 2006
  • MrExcite96

    MrExcite96

    17 ŞUBAT 2011