【发布时间】:2014-11-28 12:55:43
【问题描述】:
我正在从事一个现有的大型项目,基本上:
- 使用场景图,其中每个节点都有子槽
- 执行初始化步骤,其中每个节点递归地初始化其子节点,并对自己的数据成员执行一些预计算/清理任务。
- 然后启动大型计算,然后以纯只读模式从 const 成员函数访问场景图
目前,使用智能指针存储子级,主要是为了在从文件读取构建图形时以及在用户编辑图形期间避免深度复制。
由于智能指针(std::shared_ptr)不传播常量,我有以下选择:
- 使用指向 const 对象的智能指针存储子级。什么时候 递归地执行初始化步骤,const_cast 将它们 非常量指针 使用指向 const 的智能指针存储子项 对象。对于递归执行初始化步骤, const_cast 它们指向非常量指针。我不喜欢滥用 const_cast
- 使用指向 const 对象的智能指针存储子级。什么时候 递归地执行初始化步骤,将每个子对象深拷贝到一个非常量对象,初始化它,然后用初始化的对象替换子对象。这样效率不高,初始化时每个节点都被深度复制
- 使用指向非常量对象的智能指针存储子级。那么初始化就不再是问题了,但是在计算过程中使用的所有 const 成员函数都可能调用孩子的非 const 成员函数,这是一个潜在的错误来源,并且显然是非 const 正确的。
我知道在树操作期间仅使用智能指针来避免深度复制并不是在 c++11 时代实现这一点并移动语义的好方法。用移动语义重写所有代码可能有一天会完成,但这代表着相当大的工作。
在您看来,在不使用移动语义重写所有内容的情况下,实现该模式的最佳方式是什么?我曾想过包装 std::shared_ptr 以传播 constness,还有其他想法吗?
谢谢!
【问题讨论】:
-
使用原始指针怎么样?可能,在您的数据结构中,唯一的更改应该是节点析构函数(删除所有子节点)和节点删除方法(删除被删除的节点)。但是,如果事情比我想象的要复杂,那就做包装吧。
-
@AndreSassi 原始指针不会比智能指针更好地传播常量。使用原始指针也会让生活变得困难,尤其是节点复制行为。
-
“由于智能指针 (std::shared_ptr) 不会传播 constness” 如果这些智能指针不是公共数据成员,您可以手动执行此操作:不要修改在
const成员函数中指向的对象(并且不要在const成员函数中提供对该对象的非常量访问)。 -
@dyp :是的,但是错误总是可能的,例如调用子的非常量成员函数。编译器不会抱怨。如果您必须手动考虑不在 const 函数中执行非常量操作,那么 const 的全部目的就失去了
-
您可以将智能指针包装在提供“深度常量”的类中..
标签: c++ c++11 constants smart-pointers