簡體   English   中英

如何將 shared_ptr 變量 push_back 到 C++ 中的 shared_ptr 向量?

[英]How do you push_back a shared_ptr variable to a vector of shared_ptrs in C++?

我是 C++ 的初學者,具有 Python、Java 和 JS 的背景,所以在指針方面我仍在學習中。

我有一個共享指針向量。 在另一個 function 中,我將一個共享指針分配給一個變量並將其添加到向量中。 如果我在 function 退出后嘗試訪問添加的元素,則會發生分段錯誤:

class Bar
{
private:
    std::vector<std::shared_ptr<Foo>> fooVector;
}

void Bar::addToFoo()
{
    std::shared_ptr<Foo> foo (new Foo(…));
    fooVector.push_back(foo);
}
void Bar::otherMethod()
{
    // this method gets called sometime after addToFoo gets called
    …
    fooVector[anIndex]->baz(); // segfaults
    …
}

但是,如果 push_back 是一個共享指針而不是一個變量,它就可以工作。

// this works:
fooVector.push_back(std::shared_ptr<Foo>(new Foo(…)));

// this segfaults:
std::shared_ptr<Foo> foo (new Foo(…));
fooVector.push_back(foo);

我相信這是因為foo變量在addToFoo function 退出時被刪除(如果我錯了請糾正我)。 如何將shared_ptr變量push_back到 C++ 中的shared_ptrs vector


為什么使用變量

雖然直接將shared_ptr推入向量而不使用變量是可行的,但我更喜歡使用變量來做到這一點:

std::shared_ptr<Rider> rider;
switch (iProcessorModesParam)
{
    case PEAKS_MODE:
        rider = std::shared_ptr<Rider>(new PeaksRider(…));
        break;
    case RMS_MODE:
        rider = std::shared_ptr<Rider>(new RMSrider(…));
        break;
}
volumeRiders.push_back(rider);

PeaksRider 和 RMSrider 是 Rider 的子類。 我想將 Rider 的所有子類型存儲在相同的 Riders 向量中。 我了解到,將 Rider 的子類型添加到 Riders 的向量中是行不通的,需要指針才能實現這種多態性:

std::vector<Rider> // doesn’t work with subtypes

std::vector<*Rider>
std::vector<std::shared_ptr<Rider>>

擁有std::shared_ptr<Rider> rider; 變量避免為每種類型的 Rider 重復.push_back(…)代碼。

不是分配共享指針,而是用戶reset方法。

rider.reset(new PeaksRider(…));

除此之外,您的代碼片段對我來說似乎沒問題。

段錯誤可能是由於索引變量(可能超出范圍)引起的。 我建議您使用.at(index)從 vector 訪問指針並將該部分代碼包裝在try..catch塊中,看看真正的錯誤是什么。

而關於...

我相信這是因為 foo 變量在 addToFoo function 退出時被刪除(如果我錯了請糾正我)。

這不是真的,share_ptrs 使用本地計數器來獲取 #of 引用。 一旦您將指針推向向量,計數器就會增加到 2,並且在控制退出 function 之后,計數器就會減少到 1。因此,您的 object 尚未被銷毀。

創建共享指針實例,將其存儲在變量中,然后對向量執行 push_back 沒有問題。 只要您在調用“otherMethod”時使用的索引有效,您的代碼就應該沒問題。 但是,我對您的代碼有一些建議:

  • 當您創建一個 shared_ptr 時,強烈建議通過“std::make_shared”來創建,以確保您的代碼在所有情況下的安全性和正確性。 在另一篇文章中,您會找到一個很好的解釋: Difference in make_shared and normal shared_ptr in C++
  • 當使用可能包含會導致越界訪問(通常會導致分段錯誤)的值的變量訪問向量的位置時,最好在使用向量之前放置斷言,這樣你就會檢測到這些不需要的情況。

我剛剛寫了一個小片段,您可以測試它來說明我剛才提到的內容:

#include <iostream>
#include <vector>
#include <memory>
#include <cassert>

class Foo
{
public:
    int data = 0;
};

class Bar
{
public:
    void addNewFoo(int d)
    {
        std::shared_ptr<Foo> foo(new Foo());
        foo->data = d;
        fooVector.push_back(foo);
    }

    void addNewFooImproved(int d)
    {
        auto foo = std::make_shared<Foo>();
        foo->data = d;
        fooVector.push_back(foo);
    }

    void printFoo(int idx)
    {
        assert(idx < fooVector.size());
        std::cout << fooVector[idx]->data << std::endl;
    }

private:
    std::vector<std::shared_ptr<Foo>> fooVector;
};

int main()
{
    Bar b;
    b.addNewFoo(10);
    b.addNewFoo(12);
    b.addNewFooImproved(22);
    b.printFoo(1);
    b.printFoo(2);
    b.printFoo(0);
}

暫無
暫無

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

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