简体   繁体   English

如何将带有指针的结构插入 map?

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

I'm trying to insert a C struct from a third-pary library into a map.我正在尝试将来自第三方库的 C 结构插入到 map 中。 The problem is, the struct contains a pointer to other structs as a member field and when inserting this into my_map, the S2.arr field seems to be getting over written and I'm not sure why.问题是,该结构包含一个指向其他结构的指针作为成员字段,当将其插入 my_map 时,S2.arr 字段似乎被覆盖了,我不知道为什么。

I've been able to reproduce this have have it running here.我已经能够重现它并让它在这里运行。

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

I know the shared_ptr's may seem to confuse things, but I've left my main containers in place as it's how my larger app is accessing things.我知道 shared_ptr 可能会让人感到困惑,但我已经将我的主要容器留在原处,因为这是我的大型应用程序访问事物的方式。 Here's what I've pieced together to reproduce the problem I'm having.这是我拼凑起来的,以重现我遇到的问题。

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;
        }
    }
}

My intention is to have this print the following:我的意图是打印以下内容:

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

Yet what I'm getting is this:然而我得到的是:

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

Update: Made some edits as maps only contain unique keys.更新:进行了一些编辑,因为地图仅包含唯一键。

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

On each iteration of the for loop that has this statement, this overwrites the previous value of array that was created on the last iteration of this for loop.在具有此语句的for循环的每次迭代中,这将覆盖在此for循环的最后一次迭代中创建的array的先前值。

Since this is the only and the last smart pointer reference to the vector, the previous array always gets destroyed.由于这是对向量的唯一也是最后一个智能指针引用,因此前一个array总是被破坏。 On each iteration of the for-loop, because this std::shared_ptr does not wind up anywhere else, the vector created on the previous iteration of the loop will go to the big bit bucket in the sky.在 for 循环的每次迭代中,因为这个std::shared_ptr不会在其他任何地方结束,所以在循环的前一次迭代中创建的向量将 go 到天空中的大比特桶。

But before this happens, with each reincarnation of std::vector , later in this for loop we have:但在此之前,随着std::vector的每次转世,在这个for循环的后面,我们有:

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

Two problems here:这里有两个问题:

1) This std::move accomplishes absolutely nothing useful whatsoever, here. 1)这个std::move在这里绝对没有任何用处。 But, more importantly:但是,更重要的是:

2) As you know, data() returns an internal pointer to the vector's underlying storage. 2) 如您所知, data()返回指向向量底层存储的内部指针。 But on the next iteration of the loop, this array gets destroyed, as I explained above, leaving a dangling pointer to the contents of the destroyed vector, behind.但是在循环的下一次迭代中,这个array被破坏了,正如我上面解释的那样,留下一个指向被破坏向量内容的悬空指针,在后面。

As such, subsequent usage of the pointer becomes undefined behavior.因此,指针的后续使用变成了未定义的行为。 With or without std::move (which means nothing here).有或没有std::move (这里没有任何意义)。

To fix this, you need to take into greater consideration what smart pointers are;要解决这个问题,您需要更多地考虑智能指针是什么; and how they work;以及它们是如何工作的; what std::vector is, what its data() method returns; std::vector是什么,它的data()方法返回什么; object lifetime and scoping in C++; object 的生命周期和 C++ 中的范围; then combine this together in a way that makes it work for your program correctly.然后将其组合在一起,使其正确地适用于您的程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM