簡體   English   中英

使用指針訪問std :: map中的值是明智的嗎?

[英]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后無效, clearassignoperator= ),然后使用iteratorconst_iterator::mapped_type* ,或::mapped_type const*都是有效的。 此外,如果始終保證返回存在,則::mapped_type&::mapped_type const&也是有效的。

至於明智的,我更喜歡const版本而不是可變版本,我更喜歡對迭代器的指針進行引用。

返回迭代器與指針是不好的:

  • 它公開了一個實現細節。
  • 使用它是很尷尬的,因為調用者必須知道取消引用迭代器,結果是std :: pair,然后必須調用.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.

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