【问题标题】:Is it possible to have a static object and a static std::shared_ptr pointing to the same object? [duplicate]是否可以有一个静态对象和一个静态 std::shared_ptr 指向同一个对象? [复制]
【发布时间】:2017-11-28 22:51:51
【问题描述】:

给定以下类:

class Foo : public Base {
public:
  static const Foo FOO;
  static const std::shared_ptr<Foo> FOO_PTR;
  // .. virtual methods, etc
};

是否有可能使FOO_PTR 指向FOO

这似乎很难,因为创建共享指针的常用方法是获取动态创建的指针的所有权(例如,通过new Foo{})或通过std::make_shared&lt;Foo&gt;(),两者都创建一个新对象并且实际上不允许您将shared_ptr 指向FOO。同样,如果我先创建指针,它将与FOO 具有不同的身份,所以我想我也搞砸了。

一个非常肮脏的黑客可能是这样的:

Foo Foo::FOO = Foo{};
std::shared_ptr<Foo> Foo::FOO_PTR = &Foo::FOO;  // dirty hack
Foo* dummy = new shared_ptr<Foo>(FOO_PTR);      // leaky, yuck

基本上,我们首先创建静态FOO 对象,然后使用指向该对象的指针初始化shared_ptr&lt;FOO&gt;。现在当然这个对象不是通过new 创建的,所以如果shared_ptr 试图删除它,世界可能会结束。为了解决这个问题,我们要做的最后一件事是从第一个 shared_ptr 创建另一个 shared_ptr,增加它的引用计数,然后泄漏它,所以原来的 shared_ptr 永远不会尝试删除它的指针。

当然,这让我感到恶心,我正在寻找更好的解决方案。

现在一个显而易见的解决方案不会首先公开FOO 和/或FOO_PTR 静态对象,但我的双手被绑在这里,我无法更改设计的那部分。

【问题讨论】:

  • 为什么要让共享指针指向非动态分配的对象?
  • 您不会使用shared_ptr,因为重点是管理堆内存,而您在这里没有。你想要static const Foo* FOO_PTR;
  • @juanchopanza - 因为使用 shared_ptr 来保存 Foo 类型的对象(特别是许多其他类型,如 Foo 共享一个公共基类和 virtual 函数)被嵌入到 API .这些对象中的大多数实际上是动态创建和销毁的,shared_ptr 的使用是常规的,但也有一些像 FOOFOO_PTR 这样的单例对象,它们只创建一次,但必须与现有的 shared_ptr API 配合使用.
  • @zzxyz - 当然这就是我在这个简单示例中想要的,但是在实际用例中我的双手被绑在这里,这绝对不简单。 shared_ptr&lt;Foo&gt; 的使用被广泛使用并嵌入到 API 中,如果不付出巨大的努力并且不破坏与无数现有客户端的二进制兼容性,就无法更改。这不是设计问题:设计很糟糕,我承认。这是一个关于如何将损害降到最低的务实问题。
  • 你可以传递一个自定义的、什么都不做的删除器...或者使用“aliasing”构造函数到一个虚拟的共享ptr ...

标签: c++ shared-ptr


【解决方案1】:

不确定它是否可以帮助您解决 API 限制,但您可以通过动态创建 shared_ptr-object 并让 foo 的类型为 Foo&amp; 然后:

class Foo {
public:
    static const Foo &FOO;
    static const std::shared_ptr<Foo> FOOPTR;
};

const std::shared_ptr<Foo> Foo::FOOPTR = make_shared<Foo>();
const Foo &Foo::FOO = *Foo::FOOPTR;

int main() {
    const Foo* f1 = Foo::FOOPTR.get();
    const Foo* f2 = &Foo::FOO;

    printf("%p == %p \n",(void*)f1,(void*)f2);
}

【讨论】:

  • 谢谢,这实际上让我走到了一半:它与源代码兼容,但仍会破坏与现有客户端的二进制兼容性(因为引用在 ABI 级别是不同的类型)。不过,这是一个很好的半步。借助一些链接器魔术,可以进行渐进式转换。
猜你喜欢
  • 2012-06-08
  • 2012-08-22
  • 1970-01-01
  • 2012-11-19
  • 2013-08-06
  • 1970-01-01
  • 2020-05-30
  • 2022-09-30
  • 1970-01-01
相关资源
最近更新 更多