[英]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.