【问题标题】:use unique_ptr to wrap and unwrap void*使用 unique_ptr 包装和展开 void*
【发布时间】:2021-03-30 00:17:18
【问题描述】:

我的目标是创建 unique_ptr ,其中 void* 可以指向任何对象类型。这给了我一种使用 unique_ptr 指向共享相同签名的状态对象的方法。但是下面的代码似乎不符合我的预期,其中 p.get() 应该等于 v 和 s1 地址。我怀疑它必须尝试在 s1 顶部包装 unqiue_ptr 来拥有它。但是地址变了。

struct State1 
{
public:
  std::string name;
  std::string address;
};

int main() {

  auto s1 = new State1;
  s1->name = "name";
  std::cout<<"s1 address: "<<s1<<"\n";
  auto v = (void*)s1;
  std::cout<<"v address: "<<v<<"\n";
  auto p = std::make_unique<void*>(s1);
  std::cout<<"p.get address: "<<p.get()<<"\n";
  auto r =  static_cast<State1*>((void*)p.get());
  std::cout<<"r address: "<<r<<"\n";
}

s1 address: 0x55dcf389aeb0
v address: 0x55dcf389aeb0
p.get address: 0x55dcf389b310
r address: 0x55dcf389b310

【问题讨论】:

  • delete p;pvoid* 不会很好。您必须将自己的 deleter 提供给 unique_ptr,它可以将指针转换为正确的类型以将其删除。
  • “我的目标是创建 unique_ptr,其中 void* 可以指向任何对象类型。” 我不明白这样做的目的是什么。 std::unique_ptr&lt;T&gt; 已经可以指向任何 T?!?
  • "我的目标是创建unique_ptr&lt;void*&gt;,其中void* 可以指向任何对象类型" - 这不是std::unique_ptr 的使用方式。你为什么要这个?也许std::any 会更有意义?

标签: c++ c++11 c++14 c++17


【解决方案1】:

std::unique_ptr&lt;void*&gt; 是一个唯一的指向指针 的指针,指向 void。指向对象的指针与指向的对象是分开的。换句话说,指针和指向的对象具有不同的地址。指向 void 的指针的值是指向对象的地址,而指向 void 的指针的值是指向对象的指向 void 的指针的地址。

p.get() 为您提供唯一指针拥有的void* 对象的地址(即指向)。为了从(unique) 指向void 的指针中获取指向void 的指针,必须通过(unique) 指向void 的指针来间接获得。这给出了等于s1v 的地址:

std::cout << *p;

附:你永远不会删除动态分配的State1,因此你有内存泄漏。

【讨论】:

    【解决方案2】:

    std::unique_ptr&lt;void*&gt; 是一个指向指针的智能指针。

    您希望 unique_ptr&lt;void&gt; 作为第一步。

    接下来你需要的是达到那个唯一的ptr如何删除资源;默认情况下,unique ptr 只调用 delete,这不适用于 void 指针。它无法知道 void 指针中存储的类型,因此无法调用析构函数。

    template<class T>
    std::unique_ptr<void, void(*)(void*)>
    wrap_ptr(T* ptr){
      return {ptr, [](void*ptr){ delete static_cast<T*>(ptr); }};
    }
    

    这里我们记住了如何通过存储一个指向知道真实类型的代码的函数指针来删除对象。

    auto p = wrap_ptr(s1);
    

    我怀疑代码可以满足您的要求。

    顺便说一句,C 演员的((void*)p.get()) 隐藏了一条错误消息,说明你做错了什么。避免使用 C 风格的强制转换。

    您将void** 重新解释为void* 的事实应该是一个危险信号。

    【讨论】:

      猜你喜欢
      • 2021-12-26
      • 1970-01-01
      • 2022-08-21
      • 1970-01-01
      • 2014-05-03
      • 1970-01-01
      • 1970-01-01
      • 2011-04-27
      • 1970-01-01
      相关资源
      最近更新 更多