从共享指针的取消引用值中获取共享指针
Get a shared pointer from a dereferenced value of a shared pointer
想象一下有一个共享指针向量
typedef vector< shared_ptr< classA > > PointerVector;
还有一个 Class B,它也有一个共享指针向量的成员,以及一个将已经取消引用的共享指针推回到这个向量中的方法。
ClassB
{
public:
void add(classA &ref);
private:
PointerVector vector;
}
假设 main 为 add 函数提供一个取消引用的 shared_ptr 实例:
主要内容:
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 );
}
注意 1: 当将 classA 添加到 vector 时,我希望共享指针计数增加 1。我不需要创建另一个共享指针,我想 "find" 对象以前拥有的共享指针。
注意 2: 我不能使用 make_shared 因为我目前在 tr1
有一种方法可以做到这一点,但需要它可能意味着存在设计缺陷。
为什么它不起作用
A shared_ptr
需要一个引用计数器才能工作。此计数器保存在创建第一个 shared_ptr
时创建的控制块中。当您复制 shared_ptr
时,副本不仅复制了指向托管对象的指针,还复制了指向控制块的指针。这允许它访问引用计数器并在销毁对象时销毁块。
采用 ClassA &
的函数无权访问控制块。尝试创建一个新的 shared_ptr
将创建一个引用计数为 1 的新控制块。当任一引用计数器达到 0 时,该对象将被销毁。因此,它会被销毁两次,这是未定义的行为。
它是如何工作的
如评论中所述,std::enable_shared_from_this
解决了您的问题。你必须让你的 class 从它派生。
ClassA : std::enable_shared_from_this<ClassA> {...}
然后您可以调用 ClassA.shared_from_this()
来获取 shared_ptr
,它是同一对象的现有 shared_ptr
的副本。
为什么我不推荐使用它
你必须非常小心enable_shared_from_this
。 cppreference.com 州
It is permitted to call shared_from_this only on a previously shared object, i.e. on an object managed by std::shared_ptr. Otherwise the behavior is undefined (until C++17)std::bad_weak_ptr is thrown (by the shared_ptr constructor from a default-constructed weak_this) (since C++17).
因此,在尝试使用 shared_from_this
方法从中创建新的 shared_ptr
之前,您必须确保该对象已经共享。
此外,您的函数签名接受 ClassA&
。它可以用堆栈上的参数调用;从堆栈对象创建 shared_ptr
是危险的。如果您的函数需要共享所有权,它应该只接受 shared_ptr<ClassA>
以传达其意图。这使得它可以自我记录,并且在不牺牲任何东西的情况下更难处理不当。
通常你不能只 "find" 指向对象的指针,因为没有任何东西可以跟踪是否指向特定对象。您应该自己设计这种机制或使用标准库提供的一种机制:enable_shared_from_this
.
第 1 步:从 std::enable_shared_from_this
派生您的 class 并提供一个成员函数来获取指针:
#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 );
}
想象一下有一个共享指针向量
typedef vector< shared_ptr< classA > > PointerVector;
还有一个 Class B,它也有一个共享指针向量的成员,以及一个将已经取消引用的共享指针推回到这个向量中的方法。
ClassB
{
public:
void add(classA &ref);
private:
PointerVector vector;
}
假设 main 为 add 函数提供一个取消引用的 shared_ptr
主要内容:
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 );
}
注意 1: 当将 classA 添加到 vector 时,我希望共享指针计数增加 1。我不需要创建另一个共享指针,我想 "find" 对象以前拥有的共享指针。
注意 2: 我不能使用 make_shared 因为我目前在 tr1
有一种方法可以做到这一点,但需要它可能意味着存在设计缺陷。
为什么它不起作用
A shared_ptr
需要一个引用计数器才能工作。此计数器保存在创建第一个 shared_ptr
时创建的控制块中。当您复制 shared_ptr
时,副本不仅复制了指向托管对象的指针,还复制了指向控制块的指针。这允许它访问引用计数器并在销毁对象时销毁块。
采用 ClassA &
的函数无权访问控制块。尝试创建一个新的 shared_ptr
将创建一个引用计数为 1 的新控制块。当任一引用计数器达到 0 时,该对象将被销毁。因此,它会被销毁两次,这是未定义的行为。
它是如何工作的
如评论中所述,std::enable_shared_from_this
解决了您的问题。你必须让你的 class 从它派生。
ClassA : std::enable_shared_from_this<ClassA> {...}
然后您可以调用 ClassA.shared_from_this()
来获取 shared_ptr
,它是同一对象的现有 shared_ptr
的副本。
为什么我不推荐使用它
你必须非常小心enable_shared_from_this
。 cppreference.com 州
It is permitted to call shared_from_this only on a previously shared object, i.e. on an object managed by std::shared_ptr. Otherwise the behavior is undefined (until C++17)std::bad_weak_ptr is thrown (by the shared_ptr constructor from a default-constructed weak_this) (since C++17).
因此,在尝试使用 shared_from_this
方法从中创建新的 shared_ptr
之前,您必须确保该对象已经共享。
此外,您的函数签名接受 ClassA&
。它可以用堆栈上的参数调用;从堆栈对象创建 shared_ptr
是危险的。如果您的函数需要共享所有权,它应该只接受 shared_ptr<ClassA>
以传达其意图。这使得它可以自我记录,并且在不牺牲任何东西的情况下更难处理不当。
通常你不能只 "find" 指向对象的指针,因为没有任何东西可以跟踪是否指向特定对象。您应该自己设计这种机制或使用标准库提供的一种机制:enable_shared_from_this
.
第 1 步:从 std::enable_shared_from_this
派生您的 class 并提供一个成员函数来获取指针:
#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 );
}