簡體   English   中英

如何將帶有指針的結構插入 map?

[英]How to insert a struct with pointers into map?

我正在嘗試將來自第三方庫的 C 結構插入到 map 中。 問題是,該結構包含一個指向其他結構的指針作為成員字段,當將其插入 my_map 時,S2.arr 字段似乎被覆蓋了,我不知道為什么。

我已經能夠重現它並讓它在這里運行。

http://coliru.stacked-crooked.com/a/7c47a5c7c7294a49

我知道 shared_ptr 可能會讓人感到困惑,但我已經將我的主要容器留在原處,因為這是我的大型應用程序訪問事物的方式。 這是我拼湊起來的,以重現我遇到的問題。

typedef struct {
    int index;
    int value;
} S1;

typedef struct {
    int index;
    int num;
    S1 *arr;
} S2;

// populate new_vec with S1 if idx equals S1.index.
void find(int idx, 
    std::shared_ptr<std::vector<S1>> vec, 
    std::shared_ptr<std::vector<S1>> new_vec)
{
    for (const auto& s1 : *vec) {
        if (idx == s1.index) {
            new_vec->push_back(s1);
        }
    }
}

int main()
{
    bool found = false;

    std::shared_ptr<std::vector<S1>> array;
    std::shared_ptr<std::map<int, S2>> my_map = std::make_shared<std::map<int, S2>>();
    std::shared_ptr<std::vector<S1>> vec = std::make_shared<std::vector<S1>>();
    std::shared_ptr<std::vector<S1>> new_vec = std::make_shared<std::vector<S1>>();

    // initialize vec
    for (int i = 0; i < 3; ++i)
        vec->push_back(S1 { 1, i});

    for (int i = 0; i < 4; ++i) 
        vec->push_back(S1 { 2, i});

    for (const auto& s1 : *vec) {
        found = false;

        array = std::make_shared<std::vector<S1>>();

        // populate array with S1.indices that equal 1.
        find(s1.index, vec, array);

        my_map->insert(std::pair<int, S2>(s1.index, 
            S2 {
                s1.index,
                static_cast<int>(array->size()), 
                std::move(array->data())
            } 
        ));
    }

    for (const auto& [key, val] : *my_map) {
        std::cout << "key: " << key << std::endl;

        for (int i = 0; i < val.num; ++i) {
            S1 s = val.arr[i];
            std::cout << "  index: " << s.index << ", val: " << s.value << std::endl;
        }
    }
}

我的意圖是打印以下內容:

key: 1
  index: 1, val: 0
  index: 1, val: 1
  index: 1, val: 2
key: 2
  index: 2, val: 0
  index: 2, val: 1
  index: 2, val: 2
  index: 2, val: 3

然而我得到的是:

key: 1
  index: 2, val: 0
  index: 2, val: 1
  index: 2, val: 2
key: 2
  index: 2, val: 0
  index: 2, val: 1
  index: 2, val: 2
  index: 2, val: 3

更新:進行了一些編輯,因為地圖僅包含唯一鍵。

array = std::make_shared<std::vector<S1>>();

在具有此語句的for循環的每次迭代中,這將覆蓋在此for循環的最后一次迭代中創建的array的先前值。

由於這是對向量的唯一也是最后一個智能指針引用,因此前一個array總是被破壞。 在 for 循環的每次迭代中,因為這個std::shared_ptr不會在其他任何地方結束,所以在循環的前一次迭代中創建的向量將 go 到天空中的大比特桶。

但在此之前,隨着std::vector的每次轉世,在這個for循環的后面,我們有:

 std::move(array->data())

這里有兩個問題:

1)這個std::move在這里絕對沒有任何用處。 但是,更重要的是:

2) 如您所知, data()返回指向向量底層存儲的內部指針。 但是在循環的下一次迭代中,這個array被破壞了,正如我上面解釋的那樣,留下一個指向被破壞向量內容的懸空指針,在后面。

因此,指針的后續使用變成了未定義的行為。 有或沒有std::move (這里沒有任何意義)。

要解決這個問題,您需要更多地考慮智能指針是什么; 以及它們是如何工作的; std::vector是什么,它的data()方法返回什么; object 的生命周期和 C++ 中的范圍; 然后將其組合在一起,使其正確地適用於您的程序。

暫無
暫無

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

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