SORU
13 Kasım 2011, Pazar


Nasıl bir kurucu veya bir işlev için unique_ptr bir argüman mı?

C 11 semantiği hareket yeniyim ve kurucular veya işlevleri unique_ptr parametreleri işlemek için nasıl çok iyi bilmiyorum. Bu sınıf kendisine başvuran düşünün:

#include <memory>

class Base
{
  public:

    typedef unique_ptr<Base> UPtr;

    Base(){}
    Base(Base::UPtr n):next(std::move(n)){}

    virtual ~Base(){}

    void setNext(Base::UPtr n)
    {
      next = std::move(n);
    }

  protected :

    Base::UPtr next;

};

Fonksiyonları unique_ptr argüman alacak mı yazsam nasıl olur?

Ve arama kodu std::move kullanmam gerekiyor?

Base::UPtr b1;
Base::UPtr b2(new Base());

b1->setNext(b2); //should I write b1->setNext(std::move(b2)); instead?

CEVAP
13 Kasım 2011, Pazar


Burada bir argüman olarak benzersiz bir işaretçi almak için olası yolları yanı sıra bunların ilişkili anlamı.

(A) Değerine Göre

Base(std::unique_ptr<Base> n)
  : next(std::move(n)) {}

Sırada kullanıcı bu görüşme yapmak için, aşağıdakilerden birini yapmanız gerekir:

Base newBase(std::move(nextBase));
Base fromTemp(std::unique_ptr<Base>(new Base(...));

Değer benzersiz bir işaretçi almak anlamına gelirtransferişlev/işaretçi sahipliğini soru/etc nesne. newBase, nextBase garanti veriyor inşa edilmiştir sonraboş. Nesnenin sahibi değilsiniz, ve hatta bir işaretçi artık yok. Gitti.

Bu parametre değeri alıyoruz çünkü sağlanmaktadır. std::move aslında değilhareket ettirinhiçbir şey, sadece süslü bir kadro. std::move(nextBase) nextBase r-değeri bir referans olduğunu Base&& döndürür. O öyle şey.

Base::Base(std::unique_ptr<Base> n) r-değeri referans değer yerine argüman alır, çünkü, C otomatik olarak bizim için geçici bir yapı olacak. std::move(nextBase)) fonksiyonu verdiğimiz Base&& std::unique_ptr<Base> bir oluşturur. Bu geçici inşası aslındataşırişlev bağımsız değişken n içine nextBase değeri.

(B) olmayan sabit Tarafından l-değeri referans

Base(std::unique_ptr<Base> &n)
  : next(std::move(n)) {}

Bu l-değeri (adında bir değişken) bir gerçek " olması gerekiyor. Böyle bir geçici ile çağrılamaz:

Base newBase(std::unique_ptr<Base>(new Base)); //Illegal in this case.

Bu olmayan sabit referanslar herhangi bir anlamı aynıdır anlamı: işlev olabilirya da olmayabilirişaretçi sahipliğini iddia ediyor. Verilen bu kod:

Base newBase(nextBase);

nextBase boş olduğunu garanti diye bir şey yok.olabilirboş olabilir; olmayabilir. Gerçekten Base::Base(std::unique_ptr<Base> &n) ne yapmak istediğini bağlıdır. Bu yüzden, ne olacağını işlev imzası sadece çok belirgin değil; uygulama (veya ilişkili belgeler) okumalısın.

Bu nedenle, bir arayüz olarak tavsiye etmem.

(C) sabit l-değeri referans

Base(std::unique_ptr<Base> const &n);

Bir uygulama, çünkü yokolamazconst& bir hareket. const& ileterek işlev işaretçisi aracılığıyla Base erişebileceği diyorsun, ama olamazmağazaher yerde. Olamaz, sahipliğini iddia ediyor.

Bu yararlı olabilir. Mutlaka özel bir durum için, ama her zaman iyi birisi bir işaretçi el ve onlar bunu bilirolamaz(döküm uzakta C kırma , kuralları olmayan, const) sahiplik iddia. Saklayın edemezler. Başkalarına geçer, ama diğerleri aynı kurallara uymak zorundayız.

(D) r-değeri referans

Base(std::unique_ptr<Base> &&n)
  : next(std::move(n)) {}

Bu "olmayan sabit l-değeri referans" diye. daha fazla veya daha az aynıdır Farklılıkları iki şey vardır.

  1. Sanaolabilirgeçici pass:

    Base newBase(std::unique_ptr<Base>(new Base)); //legal now..
    
  2. Sanagerekirgeçici olmayan argümanlar geçerken std::move kullanın.

İkincisi gerçekten sorun. Eğer bu satır görürseniz:

Base newBase(std::move(nextBase));

Bu hat tamamlandıktan sonra nextBase boş olması makul bir beklenti var. Taşınmış olmalıydı. Sonuçta, std::move orada, o hareketi anlatıyor oturan oluştu.

Sorun değil. Değilgarantiliiçin taşınmış.olabilirtaşındı olmuştur, ama sadece kaynak koduna bakarak bilirsiniz. Yapamazsınız sadece işlev imzası anlatıyor.

Öneriler

  • (A) Değeri:Bir işlev iddia etmesi demekmülkiyetbir unique_ptr, değer.
  • (C) l-değeri referans inş:Eğer bir işlev, yalnızca işlevin yürütme süresi unique_ptr kullanmak için diyorsan const& tarafından götürün. Alternatif olarak, gerçek türü için işaret etti, yerine unique_ptr kullanarak & const& pass.
  • (D) r-değeri referans:Bir işlevi olabilir veya mülkiyet (iç kod yollara bağlı olarak) iddia edebilir, o zaman && ile götürün. Ama ben şiddetle mümkünse bunu yaparken karşı tavsiye.

Nasıl unique_ptr işlemek için

unique_ptr kopyalama yapamazsınız. Sadece taşıyabilirsiniz. Bunu yapmak için doğru yolu std::move standart kütüphane fonksiyonu ile.

Eğer değer unique_ptr bir alırsan, özgürce hareket edebilirsiniz. Ama hareketi aslında std::move yüzünden olmamış. Aşağıdaki ifade:

std::unique_ptr<Base> newPtr(std::move(oldPtr));

Bu gerçekten iki ifade vardır:

std::unique_ptr<Base> &&temporary = std::move(oldPtr);
std::unique_ptr<Base> newPtr(temporary);

(Not: Yukarıdaki kod teknik olarak, geçici olmayan r-değeri başvurular aslında değil r-değerleri. beri derleme değil Burada amaç sadece gösteri için.

temporary r-değeri oldPtr başvuru. Bukurucuhareketin olduğu yerde newPtr. unique_ptr'nin bu hareketi kurucu (kendisi için && götüren bir kurucu) gerçek hareketi yapıyor.

unique_ptr bir değeri var ve bir yerde saklamak istiyorsanız, sizegerekirstd::move depolama yapmak için kullanın.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Blue Lightning TV

    Blue Lightni

    9 EKİM 2011
  • Charles Nesson

    Charles Ness

    27 NİSAN 2006
  • JorteexHD

    JorteexHD

    20 NİSAN 2012