簡體   English   中英

擁有可以指向或引用已在堆棧上分配的不同類型數據的映射的現代方法

[英]Modern way to have a map that can point-to or reference data of different types that has been allocated on the stack

使用原始指針,可以這樣實現:

#include <iostream>
#include <string>
#include <map>

using namespace std;

class base {
public:
    virtual ~base(){}
};

class derived1 : public base {
public:
    virtual ~derived1(){}
    derived1(const int& other) : val(other) {}
    int val;
};

class derived2 : public base {
public:
    virtual ~derived2(){}
    derived2(const float& other) : val(other) {}
    float val;
};


int main()
{
    derived1 dataA = 4;
    derived2 dataB = 3.0f;

    std::map<std::string, base*> mapOfPointersToData; //Needs to be a pointer because it can be of type deribed1 or derived2. Cant be smart as pointing to stack memory
    mapOfPointersToData["dataA"] = &dataA;
    mapOfPointersToData["dataB"] = &dataB;

    base* result = mapOfPointersToData["dataA"];

    std::cout << dynamic_cast<derived1*>(result)->val << std::endl;

    return 0;
}

這是可行的,但有人告訴我,我們應該避免使用原始指針,而應使用智能指針或引用。

對象永遠不能為空,因此使用引用是有意義的。 我們可以通過使用變體來解決地圖只能存儲一種數據類型的問題:

int main()
{
    derived1 dataA = 4;
    derived2 dataB = 3.0f;

    std::map<std::string, std::variant<derived1, derived2>&> mapOfPointersToData; //Cant be constructed
    mapOfPointersToData["dataA"] = dataA;
    mapOfPointersToData["dataB"] = dataB;

    auto result = mapOfPointersToData["dataA"];

    std::cout << std::get<derived1>(result).val << std::endl;

    return 0;
}

但這給出了錯誤

error: value-initialization of reference type ‘std::variant<derived1, derived2>&

那么存儲對不同類型的堆棧數據的引用的最佳方法是什么?

這是可行的,但有人告訴我,我們應該避免使用原始指針,而應使用智能指針或引用。

僅當原始指針負責擁有它們所指向的內容時(基本上,如果您必須記住delete或以其他方式釋放它們),則不鼓勵使用原始指針。 在這里,對象具有自動存儲持續時間,指針不負責清理它們。 這是原始指針的合理用例。

對象永遠不能為空,因此使用引用是有意義的。

如果您使用operator[]搜索地圖,則地圖中的對象可能為nullptr 該運算符添加它無法找到的任何元素,並且 value 初始化它們(指針為nullptr )。 如果您不想用空指針使地圖膨脹,則可以改用find

那么存儲對堆棧數據的引用的最佳方法是什么,可以是不同的類型?

您可能正在尋找std::reference_wrapper ,它將std::reference_wrapper包裝在適合容器的對象中。 但是使用base*似乎已經是一個很好的解決方案,因為您的地圖並不擁有它最終指向的對象。

如果您的目標是避免使用原始指針以支持智能指針,那么我會這樣做:

int main()
{
    std::map<std::string, std::unique_ptr<base>> mapOfPointersToData;
    mapOfPointersToData["dataA"] = std::make_unique<derived1>(4);
    mapOfPointersToData["dataB"] = std::make_unique<derived2>(3.0f);

    auto& result = mapOfPointersToData["dataA"];

    std::cout << dynamic_cast<derived1*>(result.get())->val << std::endl;

    return 0;
}

請注意,我使用make_unique<>()調用將對象創建放入堆中,以通過智能指針突出顯示所有權。

暫無
暫無

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

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