想象一下有一个共享指针的向量
typedef vector< shared_ptr< classA > > PointerVector;
还有一个B类,它还有一个共享指针向量的成员,以及一个在已经解除引用的共享指针中推回该向量的方法。
ClassB
{
public:
void add(classA &ref);
private:
PointerVector vector;
}
假设main使用dereferenced shared_ptr&lt; add函数提供add函数。 classA&gt;实例:
在main中:
shared_ptr< classA > sharedptr ( new classA );
ClassA &ref = *sharedptr;
ClassB B;
B.add(ref);
有没有办法实现add函数来接受解除引用的共享指针并将其转换为初始共享指针?然后把它推回矩阵?
这就是我想要做的事情:
void ClassB::add(classA &ref) {
shared_ptr< classA > ptr = &ref;
vector.push_back( ptr );
}
NOTE1:当将classA添加到向量时,我希望共享指针计数增加1。我不需要创建另一个共享指针,我想“找到”对象以前拥有的共享指针。
注2:我不能使用make_shared因为我目前在tr1
答案 0 :(得分:3)
通常,您不能只是“找到”指向对象的指针,因为如果指向特定对象,则无法跟踪。您应该自己设计这样的机制,或者使用标准库提供的机制:Another useful SO question。
步骤1:从std::enable_shared_from_this
派生你的类并提供一个成员函数来获取指针:
#include <memory>
struct ClassA: std::enable_shared_from_this<ClassA>
{
std::shared_ptr<ClassA> get_pointer()
{
return shared_from_this();
}
//...
};
第2步:确保您想要获取指针的所有对象都由shared_ptr
管理:
std::shared_ptr<ClassA> original_ptr(new ClassA);
步骤3:每当你想获得一个对象的共享指针时,调用步骤1中定义的函数:
void ClassB::add(classA& ref) {
shared_ptr<classA> ptr = ref.get_pointer();
vector.push_back( ptr );
}
答案 1 :(得分:2)
有一种方法可以做到这一点,但需要这可能意味着存在设计缺陷。
shared_ptr
需要一个参考计数器才能工作。此计数器保存在创建第一个shared_ptr
时创建的控制块中。复制shared_ptr
时,副本不仅仅复制指向托管对象的指针,它还会复制指向控制块的指针。这允许它访问引用计数器并在它破坏对象时销毁该块。
使用ClassA &
的函数无权访问控制块。尝试创建新的shared_ptr
将创建一个引用计数为1的新控制块。当任一引用计数器达到0时,该对象将被销毁。因此,它将被销毁两次,这是未定义的行为。
正如评论中已提到的那样,std::enable_shared_from_this
解决了您的问题。你必须让你的课程从中衍生出来。
ClassA : std::enable_shared_from_this<ClassA> {...}
然后,您可以致电ClassA.shared_from_this()
以获取shared_ptr
,该shared_ptr
是同一对象的现有enable_shared_from_this
的副本。
你必须非常小心shared_ptr
。 cppreference.com声明
允许仅在先前共享的对象上调用shared_from_this,即在由std :: shared_ptr管理的对象上。否则行为是未定义的(直到C ++ 17)抛出std :: bad_weak_ptr(由默认构造的weak_this中的shared_ptr构造函数)(自C ++ 17开始)。
因此,在尝试使用shared_from_this
方法从中创建新的ClassA&
之前,您必须确保该对象已经共享。
此外,您的函数签名接受shared_ptr
。它可以在堆栈上使用参数调用;从堆栈对象创建shared_ptr<ClassA>
是危险的。如果您的功能需要共享所有权,则它应该只接受{{1}}以便传达其意图。这使得它自我记录并且在不牺牲任何东西的情况下更难以错误处理。