[英]Is it wise to use a pointer to access values in an std::map
將指針從std::map::find
返回到數據並使用它而不是獲取數據副本是否危險?
目前,我得到一個指向我的地圖中的條目的指針,並將其傳遞給另一個函數來顯示數據。 我擔心項目移動導致指針變為無效。 這是一個合法的問題嗎?
這是我的示例函數:
MyStruct* StructManagementClass::GetStructPtr(int structId)
{
std::map<int, MyStruct>::iterator foundStruct;
foundStruct= myStructList.find(structId);
if (foundStruct== myStructList.end())
{
MyStruct newStruct;
memset(&newStruct, 0, sizeof(MyStruct));
myStructList.structId= structId;
myStructList.insert(pair<int, MyStruct>(structId, newStruct));
foundStruct= myStructList.find(structId);
}
return (MyStruct*) &foundStruct->second;
}
毫無疑問,返回迭代器而不是指針更為典型,盡管它可能沒什么區別。
至於剩余有效:地圖迭代器保持有效,直到/除非它引用的項目從地圖中刪除/刪除。
在地圖中插入或刪除其他節點時,可能會導致地圖中的節點重新排列。 這是通過操縱節點之間的指針來完成的,因此它會更改其他節點包含指向您關注的節點的指針,但不會更改該特定節點的地址或內容,因此指向該節點的指針/迭代器仍然有效。
只要您,您的代碼和開發團隊了解std :: map值的生命周期( insert
后有效, erase
后無效, clear
, assign
或operator=
),然后使用iterator
, const_iterator
, ::mapped_type*
,或::mapped_type const*
都是有效的。 此外,如果始終保證返回存在,則::mapped_type&
或::mapped_type const&
也是有效的。
至於明智的,我更喜歡const
版本而不是可變版本,我更喜歡對迭代器的指針進行引用。
返回迭代器與指針是不好的:
.second
來獲取實際值。
.first
是用戶可能不關心的關鍵。 ::end()
,這對調用者來說顯然不可用。 這並不危險 - 指針只要迭代器或引用就會保持有效。
但是,在你的特殊情況下,我認為無論如何這不是正確的事情。 您的函數無條件地返回結果。 它永遠不會返回null。 那么為什么不返回參考?
另外,對您的代碼有一些評論。
std::map<int, MyStruct>::iterator foundStruct;
foundStruct = myStructList.find(structId);
為什么不將聲明和賦值組合到初始化中? 然后,如果你有C ++ 11支持,你可以寫
auto foundStruct = myStructList.find(structId);
然后:
myStructList.insert(pair<int, MyStruct>(structId, newStruct));
foundStruct = myStructList.find(structId);
您可以使用make_pair簡化插入。 您還可以避免冗余查找,因為insert會將迭代器返回到新插入的元素(作為對的第一個元素)。
foundStruct = myStructList.insert(make_pair(structId, newStruct)).first;
最后:
return (MyStruct*) &foundStruct->second;
不要使用C風格的演員陣容。 它可能無法達到您的預期。 此外,如果沒有必要,請不要使用演員表。 &foundStruct-> second已經有類型MyStruct *,那么為什么要插入一個演員? 它唯一能做的就是隱藏一個你需要改變的地方,比如你改變地圖的價值類型。
是,
如果在不知道使用它的情況下構建泛型函數,則返回指針(或迭代器)會很危險,因為它可能變得無效。
我建議做兩個中的一個:
1.使用std :: shared_ptr並返回。 (見下文)
2.按值返回結構(可以更慢)
//change the difination of the list to
std::map<int, std::shared_ptr<MyStruct>>myStructList;
std::shared_ptr<MyStruct> StructManagementClass::GetStructPtr(int structId)
{
std::map<int, std::shared_ptr<MyStruct>>::iterator foundStruct;
foundStruct = myStructList.find(structId);
if (foundStruct == myStructList.end())
{
MyStruct newStruct;
memset(&newStruct, 0, sizeof(MyStruct));
myStructList.structId= structId;
myStructList.insert(pair<int, shared_ptr<MyStruct>>(structId, shared_ptr<MyStruct>(newStruct)));
foundStruct= myStructList.find(structId);
}
return foundStruct->second;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.