【问题标题】:Passing std::vector of std::shared_ptr, not updating the objects传递 std::shared_ptr 的 std::vector,不更新对象
【发布时间】:2018-10-13 23:21:25
【问题描述】:

好吧,我可能做错了,但我束手无策。

我有一个节点类的 shared_ptr 向量,我传递给各种东西,我的节点类有一个节点类型的邻居的 share_ptr 向量。

我有一个类为我生成节点网格,并返回一个std::vector<std::shared_ptr<Node>> nodes 和一个重要的std::shared_ptr<Node> significant node。 然后,我将此向量传递给一个索引器,该索引器创建第二个列表,该列表是第一个列表的子集,大小约为 10%,它返回为std::vector<std::shared_ptr<Node>> indexedNodes

创建这些后,我将它们传递给另一个对象,以供以后参考。 然后修改器类从 indexedNodes 中获取单个随机节点,并使用它遍历节点邻居修改高度值。

稍后,当我将它们导出时,值显示为 0/initialized。

需要注意的一点,我将数据传递给函数并返回 std::vector<std::shared_ptr<Node>> 我认为这是我的问题,我只是不确定如何正确传递我的 shared_ptr 的容器,这样我就不会复制.

如果需要更多信息,请告诉我。我正在寻找我可以理解的示例或参考。

对不起代码,它不漂亮,我使用动态加载的库。

完成工作的函数:

void cruthu::Cruthu::Run() {
    std::shared_ptr<cruthu::ITeraGen> teraGen(this->mSettings.TeraGen.Factory->DLGetInstance());
    std::vector<std::shared_ptr<cruthu::Node>> nodes(teraGen->Create());
    std::shared_ptr<cruthu::Node> significantNode(teraGen->GetSignificantNode());

    std::vector<std::shared_ptr<cruthu::IIndexer>> indexers;
    for(const auto indexer : this->mSettings.Indexers) {
        indexers.push_back(indexer.Factory->DLGetInstance());
    }
    std::vector<std::shared_ptr<cruthu::Node>> indexedNodes(indexers.at(0)->Index(nodes));

    std::shared_ptr<cruthu::ITera> tera(this->mSettings.Tera.Factory->DLGetInstance());
    tera->SetNodes(nodes);
    tera->SetIndexedNodes(indexedNodes);
    tera->SetSignificantNode(significantNode);

    for(const auto & formaF : this->mSettings.Formas) {
        std::shared_ptr<cruthu::IForma> forma(formaF.Factory->DLGetInstance());
        forma->SetNode(tera->GetIndexedNode());
        forma->Modify();

        std::cout << std::to_string(tera->GetIndexedNode()->GetHeight()) << std::endl;
    }

    this->CreateImage(tera);
}

TeraGen:

#ifndef CRUTHU_ITERAGEN_HPP
#define CRUTHU_ITERAGEN_HPP

#include <cruthu/Node.hpp>

#include <vector>

namespace cruthu {
class ITeraGen {
public:
    virtual ~ITeraGen() = default;

    virtual std::vector<std::shared_ptr<cruthu::Node>> Create() = 0;
    virtual std::shared_ptr<cruthu::Node> GetSignificantNode() = 0;
};
} // namespace cruthu
#endif

泰拉:

#ifndef CRUTHU_ITERA_HPP
#define CRUTHU_ITERA_HPP

#include <cruthu/IIndexer.hpp>
#include <cruthu/Node.hpp>

#include <memory>
#include <vector>

namespace cruthu {
class ITera {
public:
    virtual ~ITera() = default;

    virtual void SetNodes(std::vector<std::shared_ptr<cruthu::Node>>& nodes) = 0;
    virtual void SetIndexedNodes(std::vector<std::shared_ptr<cruthu::Node>>& indexedNodes) = 0;
    virtual void SetSignificantNode(std::shared_ptr<cruthu::Node> significantNode) = 0;
    virtual std::vector<std::shared_ptr<cruthu::Node>>& GetNodes() = 0;
    virtual std::vector<std::shared_ptr<cruthu::Node>>& GetIndexedNodes() = 0;
    virtual std::shared_ptr<cruthu::Node> GetIndexedNode() = 0;
};
} // namespace cruthu
#endif

索引器:

#ifndef CRUTHU_IINDEXER_HPP
#define CRUTHU_IINDEXER_HPP

#include <cruthu/Node.hpp>

#include <memory>
#include <vector>

namespace cruthu {
class IIndexer {
public:
    virtual ~IIndexer() = default;

    virtual std::vector<std::shared_ptr<cruthu::Node>> Index(std::shared_ptr<cruthu::Node> node) = 0;
    virtual std::vector<std::shared_ptr<cruthu::Node>> Index(std::vector<std::shared_ptr<cruthu::Node>>& nodes) = 0;
};
} // namespace cruthu
#endif

形式:

#ifndef CRUTHU_IFORMA_HPP
#define CRUTHU_IFORMA_HPP

#include <cruthu/Node.hpp>

namespace cruthu {
class IForma {
public:
    virtual ~IForma() = default;

    virtual void SetNode(std::shared_ptr<cruthu::Node> node) = 0;
    virtual void Modify() = 0;
};
} // namespace cruthu
#endif

我确实更新并尝试在两者之间添加引用,这就是为什么他们现在在某些地方有引用。我仍然有同样的问题。

【问题讨论】:

  • 请提供minimal reproducible example,准确显示您实际在做什么,以及您遇到的问题
  • 我的水晶球认为你在某处复制节点。
  • 我很快就会得到一个 MCVE。
  • 使用 shared_ptrs,除非我用它调用 std::copy,否则我不会重复正确?

标签: c++ c++11 memory


【解决方案1】:

正如用户Remy Lebeau 所说,请提供一个最小、完整且可验证的示例。

正如您所说,您将 std::vector&lt;std::shared_ptr&lt;Node&gt;&gt; 从一个类传递到另一个类或从一个函数传递到另一个函数,并且它们没有更新并且初始化为 0。根据您描述的行为,我有一个问题要问您,我将其发布为答案,因为评论太长了。

您接受上述向量或共享指针的函数声明/定义是否如下所示:

void someFunc( std::vector<shared_ptr<Node> nodes ) { ... }

或者看起来像这样:

void someFunc( std::vector<shared_ptr<Node>& nodes ) { ... }

我问这个是因为如果你通过值而不是通过引用传递容器,它会有所不同。

【讨论】:

  • 谢谢,我会尽快的。第一个是我传递的。
  • @Vi1i 我认为这可能是您的问题;尝试将向量作为参考传递!
  • 我把代码贴出来了,你能看看它看起来是否正确吗?
【解决方案2】:

这不是(还)一个答案,而是确定问题的问题,因为没有提供足够的实现。

一个可能的问题(很难说没有看到实现......)是您在 Run() 函数顶部创建节点:

std::vector<std::shared_ptr<cruthu::Node>> nodes(teraGen->Create());

然后您将该函数作为此调用中的引用传递:

tera->SetNodes(nodes);

tera 对节点有什么作用?通过引用传递意味着 shared_ptr:s 的计数不会增加。

this-&gt;CreateImage(tera) 是做什么的?

Run() 完成后是否使用节点?

【讨论】:

  • 我看到你访问了 git 存储库,我对我的传递方式进行了一些更改。所以我要发布我所做的并接受它作为答案......
【解决方案3】:

我无法与上面的 cmets 一起使用,这主要是我无法提供足够信息的问题。 话虽如此,我重新编写了代码,改为将cruthu::Tera 对象作为共享指针传递,并将向量公开为类的公共成员。这是我稍后会重新讨论的内容,因为这个实现并不是我感到高兴的事情。

代码在github,不幸的是这是我的论文工作,所以我不能再等了。

如果人们仍然想尝试答案,我会与他们合作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-20
    • 2017-03-22
    • 2018-02-02
    • 2020-11-04
    • 2023-02-08
    • 1970-01-01
    • 1970-01-01
    • 2010-12-18
    相关资源
    最近更新 更多