[英]C++ shared pointers referencing an object within an array
才剛剛開始研究智能指針,以及如何使用它們來提高代碼內的效率,我很好奇shared_ptr如何與數組/向量/容器中的類對象反應。
從我讀過的共享指針的一般要點來看,一旦所有指向一個對象的指針都被破壞或重新分配,該對象也將被破壞。 但是,如果我們的對象也存儲在數組/向量中,即使共享對象仍然可以訪問,共享指針是否仍會嘗試銷毀該對象。
有沒有什么辦法可以在設置數組時設置共享指針,這樣可以確保僅在清除數組/向量后才刪除對象,還是必須在數組中使用shared_ptr?
不建議將裸引用與shared_ptr混合使用。 主要原因是因為它違反了引用計數的概念,shared_ptr用來確定何時可以安全地解除分配引用的對象。 任何裸引用的生存期必須比壽命最長的shared_ptr的生存期短,否則崩潰就會醞釀。
如果您想在某種容器中包含一組對象,並且仍然能夠使用shared_ptr訪問這些對象,則最好使用shared_ptr的數組/向量/容器,因為這會使容器“折疊” ”可以說是shared_ptr概念。 這樣做的好處是,當從容器中刪除對象時,將不會立即釋放該對象,反之亦然,引用該對象的共享指針也是如此。
使用shared_ptrs容器的缺點是,由於實際上使用的是指向指針的指針,因此指針數學變得稍微困難些。
您應該僅以兩種方式使用共享指針:
1)創建新對象時,
std::shared_ptr<something> ptr(new something);
2)當您將共享指針復制到另一個指針時。
std::shared_ptr<something> copy(ptr);
因此,如果您在數組中創建對象,則它不適合共享指針方案。
如果要在向量中保存使用共享指針分配的對象,則必須保存其共享指針:
std::vector<std::shared_ptr<something> > my_vector;
my_vector.push_back(new something);
清除向量時,所有指針都將清除,因此僅由向量引用的對象將被刪除:
my_vector.clear(); // do "delete something" as required
附帶說明一下,您在問題中說“更有效” ...共享指針並不是更有效,並且它們在軟件中創建的代碼的可能性也不會比您想象的要多。
C ++中非常重要的一點是例外。 保存在智能指針中的對象(在這種情況下,unique_ptr也起作用)將在異常時自動刪除。 這個非常重要。 例如:
std::shared_ptr<something> ptr(new something);
...
if(this_is_true) throw std::logic_error("something's wrong");
...
在上面的代碼中,指針ptr
在拋出ptr
之前自動被刪除。 這不是我所說的更有效,但是在清潔度方面要好得多。 如果您調用一個可以拋出的函數(例如,另一個new
函數),則處理每個調用將變得非常乏味(即,您需要在每次調用中都進行一次try / catch,並且catch必須刪除指針並然后重新拋出。)
因此從某種意義上講,它是有效的。 但是,就執行速度而言,它可能比不使用共享指針快(或慢)。
指向子對象(數組元素或對象成員)的指針可能與指向整個對象的指針共享所有權。 使用模板構造函數為子對象創建shared_ptr
:
template< class Y >
shared_ptr( const shared_ptr<Y>& r, T *ptr );
它接受任何類型的shared_ptr
,以及指向目標類型的指針(可能完全不相關)。 構造的shared_ptr
與源對象r
共享所有權,但是在取消引用時指向ptr
。
例如,創建一個指向std::array
的第三個array元素的指針:
class foo {};
auto array = std::make_shared<std::array<foo, 16>>();
auto element_ptr = std::shared_ptr<foo>(array, array->data() + 2);
或對象的數據成員:
struct foo {
int i;
};
auto some_foo = std::make_shared<foo>();
auto foo_member = std::shared_ptr<int>(some_foo, &some_foo->i);
可惜沒有像std::make_shared
這樣方便的類型推斷“ make”功能,明確指定子對象的類型很煩人。 也許我們應該自己寫:
template <typename Object, typename SubObject>
inline std::shared_ptr<SubObject>
make_sub_ptr(const std::shared_ptr<Object>& c, SubObject* ptr) {
return {c, ptr};
}
因此我們可以將早期的創建簡化為:
auto element_ptr = make_sub_ptr(array, array->data() + 2);
// ...
auto foo_member = make_sub_ptr(some_foo, &some_foo->i);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.