c++ - 将大对象放在堆上的最佳方法是什么?

标签 c++ c++11 bigdata heap-memory

我正在做一个项目,需要从数据文件中加载许多对象并将它们存储在内存中。因为有人告诉我堆栈空间很少,大量数据应该放在堆上,所以我把所有东西都放在堆上。然而,我的印象是我有点过头了。

我目前的设计是这样的:

class RoadMap
{
    unique_ptr<set<unique_ptr<Node>>> allNodes;

    void addNode(unique_ptr<Node> node)
    {
        this->allNodes->insert(std::move(node));
    }
}

int main()
{
    unique_ptr<RoadMap> map(new RoadMap());

    // open file etc.

    for (auto nodeData : nodesInFile)
    {
        map->addNode(unique_ptr<Node>(new Node(nodeData)));
    }
}

根据我现在的理解,这会产生大量开销,因为涉及许多我认为不需要的唯一指针。如果我没理解错的话,“指针链”中只有一个唯一的指针屏障应该就足够了。但是,我不确定执行此操作的最佳做​​法是什么。

选项1

class RoadMap
{
    unique_ptr<set<Node>> allNodes;

    void addNode (Node node)
    {
        this->allNodes->insert(node);
    }
}

int main()
{
    RoadMap map;
    //open file etc.
    for (auto nodeData : nodesInFile)
    {
        map.addNode(Node(nodeData));
    }
}

在我看来,这样做的好处是 RoadMap 类本身是唯一需要处理堆分配的类,并且只在创建 set 时这样做一次.

选项 2

class RoadMap
{
    set<Node> allNodes;

    void addNode (Node node)
    {
        this->allNodes.insert(node);
    }
}

int main()
{
    unique_ptr<RoadMap> map(new RoadMap());
    // open file etc.
    for (auto nodeData : nodesInFile)
    {
        map->addNode(Node(nodeData));
    }
}

这里唯一指针只在主函数中,这意味着 RoadMap 类的用户需要知道这个对象可能会变得非常大,应该放在堆栈上。我不认为这是一个非常好的解决方案。

选项3

class RoadMap
{
    set<unique_ptr<Node>> allNodes;

    void addNode(unique_ptr<Node> node)
    {
        this->allNodes.insert(std::move(node));
    {
}

int main()
{
    RoadMap map;
    // open file etc.
    for (auto nodeData : nodesInFile)
    {
        map.addNode(unique_ptr<Node>(new Node(nodeData)));
    }
}

此解决方案使用许多独特的指针,这意味着在删除 RoadMap 时需要调用许多析构函数和 delete。此外,RoadMap 调用者在添加节点时必须提供 unique_ptr,这意味着他必须自己进行堆分配。


目前,与其他选项相比,我更倾向于选项 1。但是,我编写 C++ 代码的时间相对较短,不确定我是否完全理解内存管理背后的概念,这就是为什么我希望您(不)验证我的观点。我假设选项 1 是执行此操作的最佳方法是否正确?对于此类事情,您是否有其他最佳实践引用?

最佳答案

Node 一个移动构造函数和移动赋值运算符(以使集合上的操作便宜),然后混合使用选项 1 和 2。std::set将已经在堆上分配其内容,因此您无需担心在堆上分配 RoadMap。请注意 addNode 中的额外 std::move 以允许将 Node 移动到集合中。

class RoadMap
{
    set<Node> allNodes;

    void addNode (Node node)
    {
        allNodes.emplace(std::move(node));
    }
};

int main()
{
    RoadMap map;
    // open file etc.
    for (const auto& nodeData : nodesInFile)
    {
        map.addNode(Node(nodeData));
    }
}

关于c++ - 将大对象放在堆上的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18329160/

相关文章:

C++/GLFW - 使用 Mutex 对象的正确方法?

c++ - 使用类c++的登录系统

c++ - 初始化表达式的每种方式的优缺点是什么?

c++ - std::basic_string 每次都会破坏空终止吗?

logging - cdh4 hadoop 中作业的详细日志在哪里?

c++ - 为什么这个混合继承程序会给出错误的输出?

c++ - 与 std::unique_ptr 关联的错误

hadoop - 运行 Spark 作业时出现奇怪的错误

hadoop - 如何分配数据和计算以最大化位置?

C++ 初学者 - 从命令行读取 3 个连续值的最佳方法?