C++ C++;11智能指针的所有权和铸造
我有一个基本实体类和派生类,比如cows和FicksC++ C++;11智能指针的所有权和铸造,c++,shared-ptr,software-design,weak-ptr,C++,Shared Ptr,Software Design,Weak Ptr,我有一个基本实体类和派生类,比如cows和Ficks using namespace std; class Entity { list<shared_ptr<Relationship>> relationships; void createRelationship(weak_ptr<Entity> other,.... other stuff) //... virtual ~Entity() } class Cow: publi
using namespace std;
class Entity
{
list<shared_ptr<Relationship>> relationships;
void createRelationship(weak_ptr<Entity> other,.... other stuff)
//...
virtual ~Entity()
}
class Cow: public Entity
{
//...
}
class Chicken : public Entity
....etc...
使用名称空间std;
类实体
{
列出关系;
无效创建关系(弱\u ptr其他,…其他内容)
//...
虚拟实体()
}
类别:公共实体
{
//...
}
类别:公共实体
等
我正在努力学习使用std智能指针正确管理内存。我现在的工作方式是,我的派生类唯一存在的地方就是共享指针的向量,比如
vector<shared_ptr<Cow>>
vector<shared_ptr<Chicken>>
etc.
向量
矢量
等
我的实体类负责管理任意两个实体之间的关系,无论它们是否具有相同的类型。为此,它保留了一个关系对象列表,这些对象看起来像
class Relationship
{
weak_ptr<Entity> from;
weak_ptr<Entity> to;
etc....
}
类关系
{
弱ptr来自;
弱ptr至;
等
}
我使用弱指针是因为牛或鸡可能会死亡,在这种情况下,它们与其他实体的关系将变得无效
这就是我的问题。我将所有内容存储为指向派生类的共享指针,但实体类中的所有代码都使用指向基类的弱指针。我经常需要将弱实体指针转换为共享Cow指针,或者将共享Cow指针转换为弱实体指针
不知何故,我的代码允许我在上面实体类的createRelationship(…)中的参数中传递共享的\u ptr对象。我真的不知道为什么会编译,我想知道这样做是否有效。我是否应该手动将其转换为弱指针,然后使用static\u pointer\u cast进行强制转换?(我问这个问题是因为我读到将共享指针作为参数传递很慢,我担心会发生这种情况)
在另一个方向,有时我知道某些关系是在同一类型的两个实体之间。为了说明我的观点,一头需要从父母那里继承其遗传基因的小牛:它搜索其关系以找到父子关系,然后访问指向其父母的弱实体指针。为了访问它们的遗传成员变量,它需要将这些指向实体的弱指针转换为指向奶牛的共享指针。我一直在使用弱\u ptr.lock()和动态\u指针\u强制转换来实现这一点
这是执行这两个(反向相关)强制转换的有效方法吗?任何一般性的评论或参考资料都是值得赞赏的,因为我正试图有效地使用这些指针 听起来你有三个主要顾虑:
以使用其值时,存储弱的\u ptr
是否有效
共享的\u ptr
构建弱的\u ptr
静态\u ptr\u cast
或动态\u指针\u cast
弱ptr
有一个from共享ptr
问题1和3更加模糊。为了解决这个问题,让我们来看看为什么您听说传递shared\u ptr
很慢。当您通过值传递shared_ptr
时,它必须复制shared_ptr
,复制它涉及基础引用计数的原子增量。这种原子增量有很多好处和坏处,但简短的版本是,如果您不需要跟踪所有权,这是一种不必要的开销。(在大多数情况下,担心这可能是过早的优化,但是C++语言希望确保在必要时你能担心这种事情。)
复制一个弱的\u ptr
——这比复制一个共享的\u ptr
快吗?我还没有运行任何基准测试,但我想不会。实际上有两个引用计数,一个用于拥有引用(shared_ptr
copies),另一个用于非拥有引用(weak_ptr
copies)。其中每一个都有相同的原子更新要求,因此速度不会明显加快。理论上,我猜想弱ptr
的析构函数不必检查结果引用计数并删除对象,因此如果您所做的只是复制,那么就少了一个分支。但这是一个不太可能的用法;您很可能会通过lock()
转换回共享的\u ptr
这让我们回到问题1的核心。从观察的弱的
获取共享的
有多少开销?大约相当于复制共享的\u ptr
的原子引用计数,加上您需要在消费代码上执行的分支,以确保它成功,或在失败时处理它。因此,与其考虑效率,不如考虑所有权和对象寿命。您是否曾经遇到过这样的情况:lock()
将返回一个空的shared\u ptr
?如果不是这样的话,你很可能会用一个观察不到的指针逃脱惩罚。如果基础共享\u ptr
对象可能在弱\u ptr
之前消失,则需要对其进行过期检查。如果这是一个瓶颈,看看你是否能找到一种方法来保证生命周期
最后回到问题3。我在这里回答这些问题时,并没有真正了解这些类型;相反,我是基于共享ptr
的工作原理。每个static\u pointer\u cast
、dynamic\u pointer\u cast
和const\u pointer\u cast
返回指向同一底层对象的共享\u ptr
实例。因此,他们执行了其参考计数的原子增量。因此,它们的开销大致相当于静态、动态或常量转换加上共享\u ptr
复制构造函数的开销。shared_ptr
部分不太可能对您的整个计划有重要意义,而在铸造部分,只有