首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >一种现代的方式,使地图可以指向或引用堆栈上已分配的不同类型的数据

一种现代的方式,使地图可以指向或引用堆栈上已分配的不同类型的数据
EN

Stack Overflow用户
提问于 2020-02-14 05:49:46
回答 2查看 50关注 0票数 1

使用原始指针,这可以像这样实现:

代码语言:javascript
复制
#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;
}

这是可行的,但有人告诉我,我们应该避免使用原始指针,而应使用智能指针或引用。

对象永远不能为空,因此使用引用是有意义的。我们可以通过使用变量来解决映射只能存储一种数据类型的问题:

代码语言:javascript
复制
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;
}

但这给出了错误

代码语言:javascript
复制
error: value-initialization of reference type ‘std::variant<derived1, derived2>&

那么,存储对不同类型堆栈数据的引用的最佳方式是什么?

EN

回答 2

Stack Overflow用户

发布于 2020-02-14 05:58:29

这是可行的,但有人告诉我,我们应该避免使用原始指针,而应该使用智能指针或引用。

只有当原始指针负责拥有它们所指向的内容时(本质上,如果您必须记住delete或以其他方式释放它们),才不鼓励使用原始指针。在这里,对象有automatic storage duration,指针不负责清理它们。这是原始指针的合理用例。

对象永远不能为空,因此使用引用是有意义的。

如果使用operator[]搜索地图,则地图中的对象可能为nullptr。该运算符添加它找不到的任何元素,并对它们进行赋值初始化(对于指针,初始化为nullptr )。如果你不想用空指针使地图变得臃肿,你可以使用find

那么,存储堆栈数据引用的最好方法是什么呢?

您可能正在寻找std::reference_wrapper,它将引用包装在适合容器的对象中。但是使用base*似乎已经是一个很好的解决方案,因为您的地图并不拥有它最终指向的对象。

票数 5
EN

Stack Overflow用户

发布于 2020-02-14 06:09:26

如果你的目标是避免原始指针而支持智能指针,这就是我要做的:

代码语言:javascript
复制
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<>()调用将对象创建放入堆中,以突出显示智能指针的所有权。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60216992

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档