簡體   English   中英

這段代碼安全嗎? 施放std :: vector <Derived*> 到std :: vector <Base*>

[英]is this code safe? cast a std::vector<Derived*> to std::vector<Base*>

基本上我有一個class A和一個class B : public A

我想將std::shared_ptr<std::vector<A*>轉換為std::shared_ptr<std::vector<B*>

問題是std::vector<B>不從std::vector<A>繼承,而smart_ptr也沒有。 所以我做了一個可怕的演員

  std::shared_ptr<VectorA> vector_a = * ((std::shared_ptr<VectorA>*)&vector_b);

代碼編譯並在那里運行,但它是安全的嗎? http://liveworkspace.org/code/3dQTz1$0

這是一個可怕的解決方案。 當您將一種類型的對象向量轉換為另一種類型時,您可能會遇到所有類型的錯誤/未定義行為。

您應該從頭開始使用std::shared_ptr<A>向量,並使用指向B類型對象的指針對它們進行初始化。

如果不可能,您可以創建一個包含std::weak_ptr<A>的新向量,以避免兩次管理這些對象。

不要那樣做。

考慮到(指向) B的向量不是(指向) A的向量,或者更確切地說,不是對(指針) A的向量的通用有效替換; 因此,有充分的理由說明你無法進行這樣的轉換。

雖然你在B的向量中所擁有的確實是一組對象(也是( A實例,考慮以下算法:

void f(vector<A>& v)
{
    A a;
    v.push_back(a);
}

現在假設你用向量B調用f() 這將嘗試將不是B的類的實例添加到應該僅包含類型B元素的集合中。

這里的解決方案是使代碼只接受一個足夠靈活的vector<A> ,以便在vector<B> 換句話說,您需要將其設為模板。 例如,您的模板只能接受從A派生的類型的向量作為參數。 使用一些SFINAE技術和類型特征(如std::is_base_of可以很容易地實現這一點。

嚴格來說,解除引用操作應該會成功。 兩個向量都是指針容器,因此將一個轉換為另一個,雖然生產代碼不可接受,但仍將使用相同的尺寸和對齊方式。

C ++提供了豐富的抽象來避免這些惡作劇,但最好將派生對象的向量填充為基類的指針。

你仍然可以投射元素:

A* a = vector_b->at (42);

給你你想要的。

現在,如果你已經編寫了將shared_ptr<vector<A*>>作為參數編寫的函數,那么你有多個解決方案可以讓你擺脫這種情況:

  • 使用shared_ptr<A*[]> shared_ptr<vector<A*>>而不是shared_ptr<vector<A*>> (它可以按您的意願工作)
  • A**作為參數(並使用vector_b->data () ):它不會將您vector_b->data ()到共享指針。
  • 更好:采取迭代器,其解引用為[智能]指針A (回想operator->鏈)
  • 使用std::vector<std::shared_ptr<A>> (浪費資源)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM