首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >场景图、共享指针与恒常传播

场景图、共享指针与恒常传播
EN

Stack Overflow用户
提问于 2014-10-03 12:59:14
回答 1查看 564关注 0票数 1

我现正进行一项现有的大型工程,基本上:

  • 使用场景图,其中每个节点都有子插槽。
  • 执行初始化步骤,其中每个节点递归地初始化其子节点,并对其自己的数据成员执行一些预data /清除任务。
  • 然后启动大量计算,然后只从const成员函数以纯只读模式访问场景图。

目前,子程序使用智能指针存储,主要是为了避免在从文件读取和图形的用户版本构建图形时进行深度复制。

由于智能指针(std::shared_ptr)不传播一致性,因此我有以下选项:

  1. 使用智能指针存储到const 的子节点。当递归地执行初始化步骤时,const_cast将使用指向const对象的智能指针存储子元素。为了递归地执行初始化步骤,请将它们const_cast到非const指针。我不喜欢滥用const_cast
  2. 使用智能指针存储到const 的子节点。递归地执行初始化步骤时,对每个子对象执行一个深拷贝,然后将其初始化,并将子对象替换为初始化的子对象。这是无效的,每个节点在初始化过程中都会被深度复制。
  3. 使用指向非const对象的智能指针存储子节点。那么初始化就不再是一个问题了,但是在计算过程中使用的所有const成员函数都可以调用子节点的非const成员函数,这是but的潜在来源,并且显然是非const-正确的。

我知道,在c++11和move语义时代,仅使用智能指针来避免树操作期间的深拷贝并不是实现这一点的好方法。用move语义重写所有代码可能有一天会完成,但这是一项相当大的工作。

在您看来,实现该模式的最佳方式是什么,而不使用移动语义重写所有这些呢?我曾经想过用std::shared_ptr包装来传播恒定性,还有其他的想法吗?

谢谢!

EN

回答 1

Stack Overflow用户

发布于 2014-10-05 02:56:28

我将使用选项3,但将子元素存储在基类或组合对象中的私有成员变量中。

只允许通过增强const正确性的getter访问子节点。

const getter返回指向-const的原始指针。非压缩器返回原始指针或共享指针。

类似于:

代码语言:javascript
复制
#include <iostream>
#include <memory>
#include <vector>

template<class Child>
class Parent {
 private: 
  std::vector<std::unique_ptr<Child>> children_;
 protected:
  ~Parent() = default;
 public:
  const Child* getChild(size_t child_number) const { 
    return children_.at(child_number).get(); 
  } 
  Child* getChild(size_t child_number) {
    return children_.at(child_number).get(); 
  } 
  size_t getNumberOfChildren() const {
    return children_.size();
  }
  void addChild(std::unique_ptr<Child> child) {
    children_.emplace_back(std::move(child));
  }
};

struct Node : Parent<Node> {
 private:
  std::string name_;
 public:
  Node(std::string name) : name_(std::move(name)) {}
  void print() const { std::cout << "Node: " << name_  << "\n";}
  void setName(const std::string& name) { name_ = name; }
  void wrong() const {
    //children_[0]->setName("Wrong"); // Not allowed
    //getChild(0)->setName("Wrong"); // Not allowed
  }
};

void printRecursive(const Node* node) {
  if (node) {
    node->print();
    for (size_t i=0; i!=node->getNumberOfChildren(); ++i)
      printRecursive(node->getChild(i)); 
  }
}

int main() {
  // Initialization
  Node root("Root");
  root.addChild(std::make_unique<Node>("Child 1"));
  root.addChild(std::make_unique<Node>("Child 2"));

  // "Computation" with pointer-to-const
  const Node* root_ptr = &root;
  printRecursive(root_ptr);
}

现场演示。

现场演示-使用构图。

在我的示例中,我使用了unique_ptr而不是shared_ptr,因为我可以使用,但是您可能有充分的理由使用shared_ptr

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

https://stackoverflow.com/questions/26179399

复制
相关文章

相似问题

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