首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++ -创建非局部变量指针的最佳方法

C++ -创建非局部变量指针的最佳方法
EN

Stack Overflow用户
提问于 2020-09-12 03:50:49
回答 2查看 164关注 0票数 0

我最近一直在重新学习C++,因为我开发了一个游戏在虚幻引擎。自从我接触C++大约3年了,从那以后我一直在使用Java。

由于java和c++之间的差异,我已经可以看出,对于类似的概念,有不同的最佳实践。

我有两个这样的方法。

代码语言:javascript
运行
复制
void UMarchingSquares::Generate(std::map<Vector2, int> automata) {
    std::map<Vector2,ControlNode*> controlNodes = getControlNodes(automata);
}

std::map<Vector2,ControlNode*> UMarchingSquares::getControlNodes(std::map<Vector2, int> automata) {
    std::map<Vector2,ControlNode*> controlNodes = std::map<Vector2, ControlNode*>();
    for(pair<Vector2,int> pair : automata) {
        Vector2 pos = pair.first;
        ControlNode node = ControlNode(pos,pair.second);
        controlNodes[pos] = &node;
    }
    return controlNodes;
}

我可能打破了几个不同的C++最佳实践,但有一个,我真的需要澄清一个特定的领域。

我正在getControlNodes()方法的for loop中初始化for loop对象。我现在知道这样做是不好的,因为我正在存储一个指向局部变量的指针,然后每个循环迭代都会超出范围。我倾向于存储指针,而不是实际的Control节点(尽管我可能会确信不是这样,因为Control node持有位置2浮点数、物质1整数和其他两个同时具有位置和材质的对象)。

创建非局部变量指针的最佳方法是什么?我知道我可以只使用"new ControlNode()",但据我所知,这是一个相当昂贵的调用,并且需要清理(这可能也很昂贵)。我将相当频繁地调用代码的这一部分,所以我希望它是高效的。

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-09-12 07:22:37

在过去的几年里,C++改变了很多,以使使用它的人的生活变得更容易。

查看您的代码,它提出了许多问题:

为什么在for-循环中,映射的值是指向的原始指针,而不是指向ControlNode的ControlNode或

  • ,为什么要编写显式类型的对(与迭代器不同),auto可以帮助您在这里拥有更少的副本

既然你的问题是关于第一个问题,我就忽略第二个问题。

从这个角度来看,您有三种修复代码的方法:

代码语言:javascript
运行
复制
std::map<Vector2,ControlNode> getControlNodes(std::map<Vector2, int> automata) {
    auto controlNodes = std::map<Vector2, ControlNode>{};
    for(auto &&pair : automata) {
        auto &&pos = pair.first;
        auto node = ControlNode(pos,pair.second);
        controlNodes[pos] = std::move(node);
    }
    return controlNodes;
}

在这段代码中,您可以看到*已经从映射中删除。这意味着ControlNode的所有权被移动而不是映射。(还请注意std::move)这类似于将int存储在作为参数输入的映射中。

但是,如果您需要内存分配,因为您将在其中移动,并且地址需要稳定,那么std::unique_ptr是一个很好的解决方案。

代码语言:javascript
运行
复制
std::map<Vector2,std::unique_ptr<ControlNode>> getControlNodes(std::map<Vector2, int> automata) {
    auto controlNodes = std::map<Vector2, std::unique_ptr<ControlNode>>{};
    for(auto &&pair : automata) {
        auto &&pos = pair.first;
        auto node = std::make_unique<ControlNode>(pos,pair.second);
        controlNodes[pos] = std::move(node);
    }
    return controlNodes;
}

如您所见,这段代码非常类似于前面的代码,我已经替换了映射中的类型,并将ControlNode的构造更改为std::make_unique。因此,您有一个包含对所分配内存的所有权的unique_ptr (只要您拥有unique_ptr,一切都是有效的)。

第三种解决方案只能在不能更改签名的情况下使用,并且在C++中被认为是错误的做法,因为它通过原始指针传递所有权。现在,调用方负责显式地清理内存,因为C++没有垃圾收集。

代码语言:javascript
运行
复制
std::map<Vector2,ControlNode*> getControlNodes(std::map<Vector2, int> automata) {
    auto controlNodes = std::map<Vector2, ControlNode*>{};
    for(auto &&pair : automata) {
        auto &&pos = pair.first;
        auto node = new ControlNode(pos,pair.second);
        controlNodes[pos] = node;
    }
    return controlNodes;
}

PS:我在代码中添加了一些auto,以使代码段之间的更改最小化。

票数 0
EN

Stack Overflow用户

发布于 2020-09-12 06:51:07

使用控制节点的向量进行存储。当您需要一个新的控制节点时,将一个附加到该向量中。不要使用指针,而是使用指向该向量的迭代器。确保预先在该向量中预留了足够的插槽,否则迭代器将失效。

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

https://stackoverflow.com/questions/63856642

复制
相关文章

相似问题

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