为了解决我的应用程序中一个非常特殊的问题,我需要一个指向已分配数据的共享指针,但对于外部世界,底层数据类型应该保持隐藏。
我可以通过创建我所有其他类都继承的某种 Root 类来解决这个问题,并在这个 Root 类上使用 shared_ptr,如下所示:
std::shared_ptr<Root>
但是:
- 我不希望我的所有类都从这个 Root 类继承,只是为了能够拥有这个共享指针
- 有时我想返回一个指向 std::vector 或 std::list 或 std::set 的共享指针...显然不是从我的 Root 类继承的
很奇怪,您似乎可以在 void 上创建一个 shared_ptr 并且这似乎可以正常工作,如下例所示:
class X
{
public:
X() {std::cout << "X::ctor" << std::endl;}
virtual ~X() {std::cout << "X::dtor" << std::endl;}
};
typedef std::shared_ptr<void> SharedVoidPointer;
int main()
{
X *x = new X();
SharedVoidPointer sp1(x);
}
x 被正确删除,在一个更大的实验中,我可以验证共享指针确实做了它需要做的事情(在最后一个 shared_ptr 熄灭后删除 x)。
这当然解决了我的问题,因为我现在可以使用 SharedVoidPointer 数据成员返回数据,并确保它在应有的位置被正确清理。
但这能保证在所有情况下都有效吗?它在 Visual Studio 2010 中显然可以工作,但是这在其他编译器上也能正常工作吗?在其他平台上?
最佳答案
您使用的 shared_ptr
构造函数实际上是一个构造函数模板,如下所示:
template <typename U>
shared_ptr(U* p) { }
它在构造函数内部知道指针的实际类型是什么(X
),并使用此信息创建一个仿函数,该仿函数可以正确删除
指针并确保调用正确的析构函数。这个仿函数(称为 shared_ptr
的“删除器”)通常与用于维护对象共享所有权的引用计数一起存储。
请注意,这仅在您将正确类型的指针传递给 shared_ptr
构造函数时才有效。如果你改为说:
SharedVoidPointer sp1(static_cast<void*>(x));
那么这将不起作用,因为在构造函数模板中,U
将是 void
,而不是 X
。然后该行为将是未定义的,因为不允许您使用 void 指针调用 delete
。
一般来说,如果你总是在 shared_ptr
的构造中调用 new
并且不分离对象的创建(new
)从获取对象的所有权(创建shared_ptr
)。
关于c++ - 共享 void 指针。为什么这行得通?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4807286/