c++ - 共享 void 指针。为什么这行得通?

标签 c++ visual-c++ c++11 shared-ptr smart-pointers

为了解决我的应用程序中一个非常特殊的问题,我需要一个指向已分配数据的共享指针,但对于外部世界,底层数据类型应该保持隐藏。

我可以通过创建我所有其他类都继承的某种 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/

相关文章:

c++ - 将不可复制的对象放入标准容器中

C++11 递归自旋锁实现

c++ - %p说明符仅用于有效的指针吗?

c++ - 如何在 std::stringstream 的后代中调用 "this"上的 operator<<?

c++ - 如何在 std::cout 中既不以科学形式也不以定点表示法输出 float ?

c++ - 如果 std::make_unique 从未被调用,为什么在默认成员初始化中不需要参数?

c++ - 与 shell 脚本不同,批处理文件不可执行吗?

c++ - 调用栈上的单例类

c++ - LNK2019 用于静态库中的内联函数

c - 信号 - 使用 CTRL-C 终止进程并使用 CTRL-Z 停止进程 + 测量时间