2017-05-08 20 views
5

Benim yaklaşımdır:Yüklemeyi ham işaretçiden std :: unique_ptr'ye doğru şekilde nasıl taşıyabilirim?

class SomeClass 
{ 
    std::vector<std::unique_ptr<MyObject>> myObjects; 
public: 
    void takeOwnership(MyObject *nowItsReallyMyObject) 
    { 
     myObjects.emplace_back(std::move(nowItsReallyMyObject)); 
    } 
}; 

Am şeyi doğru yapıyor ya daha iyi çözümler vardır?

+0

'std :: move' öğesine ihtiyacınız yok. – juanchopanza

+0

İlkel bir türde (işaretçi) std :: move' ibaresinin hiçbir anlamı yoktur (işaretçi) –

cevap

4

move gereksiz olduğunu.

Myself, bunu yapardım:

void takeOwnership(std::unique_ptr<MyObject> nowItsReallyMyObject) 
{ 
    myObjects.emplace_back(std::move(nowItsReallyMyObject)); 
} 

Ben kadarıyla "dışarı" mümkün olduğunca unique_ptr mülkiyet semantiğini taşımak istediğiniz çünkü.

bu yarar fonksiyonu yazabiliriz:

template<class T> 
std::unique_ptr<T> wrap_in_unique(T* t) { 
    return std::unique_ptr<T>(t); 
} 

böylece arayanlar şunları yapabilir:

foo.takeOwnership(wrap_in_unique(some_ptr)); 

ama daha da iyisi, daha sonra kadarıyla onlar makul olabildiğince unique_ptr semantik dışarı sınırlarını zorlayabilir.

Hatta yapabilir: Arayanların daha kolay onların T*unique_ptr içine geçiş sağlayan

template<class T> 
std::unique_ptr<T> wrap_in_unique(T*&& t) { 
    auto* tmp = t; 
    t = 0; 
    return std::unique_ptr<T>(tmp); 
} 
template<class T> 
std::unique_ptr<T> wrap_in_unique(std::unique_ptr<T> t) { 
    return std::move(t); 
} 

. Bunların hepsi T* ->unique_ptr<T> şimdi std::move ile sarılmıştır ve kaynak göstericiyi sıfırlar.

Böylece

struct I_am_legacy { 
    T* I_own_this = 0; 
    void GiveMyStuffTo(SomeClass& sc) { 
    sc.takeOwnership(wrap_in_unique(std::move(I_own_this))); 
    } 
}; 

kod

olsaydı dönüştürülebilir:

struct I_am_legacy { 
    std::unique_ptr<T> I_own_this; 
    void GiveMyStuffTo(SomeClass& sc) { 
    sc.takeOwnership(wrap_in_unique(std::move(I_own_this))); 
    } 
}; 

ve hala derler ve aynı şekilde çalışır. (I_own_this ile olan diğer etkileşimler değişebilir, ancak bunun bir kısmı zaten unique_ptr uyumlu olacaktır).

2

Sen den unique_ptr kabul etmelidir olsun-go:

class SomeClass 
{ 
    std::vector<std::unique_ptr<MyObject>> myObjects; 
public: 
    // tells the world you 0wNz this object 
    void takeOwnership(std::unique_ptr<MyObject> myObject) 
    { 
     myObjects.push_back(std::move(myObject)); 
    } 
}; 

bunu açıkça size sahipliğini almak ve ayrıca ham işaretçileri kullanarak önlemek için diğer programcıları yardımcı olmak Bu şekilde.

fazla okuma: CppCoreGuidelines R.32

+0

Teşekkürler. Ama daha fazla ilgileniyorum [CppCoreGuidelines R.33] (https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#r33-take-a-unique_ptrwidget-parameter-to-express-that-a taşımasının avantajlı-kanala yeniden-thewidget). MyObject öğesinin, işlev döndürdükten sonra silinmesini istemediğim şekilde ref olarak almam gerekiyor. Ayrıca VS2013, val ile geçmeye çalışırsam fonksiyonun silineceğini söyledi. Yoksa yanılıyor muyum? – Oliort

+0

@Oliort Fonksiyon döndükten sonra silinmez çünkü std :: move() 'inizi vektörünüzün içindeki std :: unique_ptr' haline getirebilirsiniz. Std :: move' sonrası parametre sürümü bir nullptr olur – Galik