【问题标题】:Passing a std::unique_ptr as a parameter to a function将 std::unique_ptr 作为参数传递给函数
【发布时间】:2011-09-09 15:19:05
【问题描述】:

我得到了如下结构和函数:

struct MYOVERLAPPED : public OVERLAPPED
{
    //...
};


void func1(std::unique_ptr<MYOVERLAPPED> pBuf)
{
    //...
};

我正在获得一个指向 MYOVERLAPPED 的指针,我想将它传递给 func1 函数。 我遇到的问题是,无论我尝试什么,我都会收到以下错误:

我已经尝试过的内容如下: 试一试:

std::unique_ptr<OVERLAPPED> pOver(//....)
HandleAcceptIndication(std::move(pOver));

错误:错误 1 ​​错误 C2440:“正在初始化”:无法从 '_OVERLAPPED **' 到 'MYOVERLAPPED *'

尝试2:

HandleAcceptIndication(new ACCEPT_OVERLAPPED);

错误 1 ​​错误 C2664:“HandleAcceptIndication”:无法转换 参数 1 从 'MYOVERLAPPED *' 到 'std::unique_ptr<_ty>'

任何人都知道我如何将 OVERLAPPED 的这个转换指针传递给 MYOVERLAPPED 到函数,以及为什么 Try2 也不起作用,因为我随便使用 std::unique_ptr&lt;MYOVERLAPPED&gt; pO(new MYOVERLAPPED) 确实起作用...?

【问题讨论】:

    标签: c++ function parameters compiler-errors unique-ptr


    【解决方案1】:

    虽然您不能直接从std::unique_ptr&lt;base&gt; 转换为std::unique_ptr&lt;derived&gt;,但编写一个安全 的强制转换函数并不难(即在任何情况下都不会泄漏资源,并且仅如果强制转换有效,则成功:

    template <typename Dst, typename Src>
    std::unique_ptr<Dst> unique_dynamic_cast( std::unique_ptr<Src>& ptr ) {
        Src * p = ptr.release();                             // [1]
        std::unique_ptr<Dst> r( dynamic_cast<Dst*>(p) );     // [2]
        if ( !r ) {
            ptr.reset( p );                                  // [3]
        }
        return r;                                            // [4]
    }
    

    基本思想是我们需要从std::unique_ptr中提取指针,并将其放在[1]中。我们不能直接尝试dynamic_cast,好像失败了,ptr 会释放所有权,并且内存会泄漏。然后我们尝试从本地指针到请求的指针类型执行dynamic_cast [2],并将所有权传递给r 结果唯一指针。如果dynamic_cast 失败,那么r 将为空,我们需要将内存的所有权归还给原来的std::unique_ptr [3],以便调用代码来决定如何处理它。然后我们将转换后的 std::unique_ptr 返回给 [4] 中的调用者。

    【讨论】:

    • 是否可以直接在 unique_ptr.get() 上进行 dynamic_cast 而不是 release?
    • @Incubbus: 是的,这也是可能的,但你必须确保只有一个std::unique_ptr 拥有内存的所有权(即如果dynamic_cast 成功,接下来就是释放来自原始std::unique_ptr的内存:std::unique_ptr&lt;Dst&gt; r( dynamic_cast&lt;Dst*&gt;(ptr.get()) ); if ( r ) ptr.release();
    • 但它给出了同样的错误......我问了这个问题,因为我已经尝试过了......这让我有点害怕:(......我没有私有继承或类似的东西它在结构内,所以我不知道出了什么问题:/
    • 好吧...确切地说:错误 1 ​​错误 C2681: '_OVERLAPPED *' : invalid expression type for dynamic_cast for std::unique_ptr ptr(dynamic_cast(pOverlapped .get()));
    • 适用于静态转换...不能使用 dynamic_cast,因为 OVERLAPPED 没有虚拟功能(正如我今天发现一些错误后出现的错误描述,说)...
    【解决方案2】:

    这不起作用,因为您试图在继承层次结构中以错误的方式进行转换。您正在尝试从 Base* 隐式转换为 Derived*。

    【讨论】:

      【解决方案3】:

      unique_ptr&lt;A&gt;unique_ptr&lt;B&gt; 是不相关的类型。除非在 A*B* 之间存在隐式转换(感谢 UncleBens),否则您无法在它们之间进行转换,在这种情况下并非如此。此外,您不应该使用不是您要转换的子类的实例来降低继承层次结构。在这种情况下,您尝试将OVERLAPPED 强制转换为MYOVERLAPPED,这是无效的强制转换,因为OVERLAPPED 不是MYOVERLAPPED。这就是为什么您首先无法在 unique_ptr 类型之间进行转换。

      如果您只是想将unique_ptr 传递给func1,您可以这样做:

      func1(shared_ptr<MYOVERLAPPED>(new MYOVERLAPPED));
      

      此外,通过将unique_ptr 传递给函数,原始函数中的指针被设置为NULL。如果您没有将 unique_ptr 创建为临时对象并将其传递给函数并且稍后需要使用相同的实例,请考虑使用引用或 shared_ptrs。

      【讨论】:

      • 如果A*B*之间存在隐式转换,实际上unique_ptr&lt;A&gt;unique_ptr&lt;B&gt;之间存在隐式转换。
      • @Uncle 呃,我以为我经历了这个并且做不到。我会修改我的答案...
      • 但是我必须做这样的事情,因为我正在检查一些变量并根据指标的内容从 OVERLAPPED 转换为 MYOVERLAPPED1 或 MYOVERLAPPED2。 (我之前所做的是 (MYOVERLAPPED*)pOverlapped - 它工作得很好,因为 pOverlapped 指向一个 MYOVERLAPPED [是的,我知道它只能“看到”重叠的部分])那么你会怎么做呢?还是我应该切换回本机指针 - 这不太舒服
      • @Incubbus 假设 OVERLAPPED 析构函数是虚拟的,并且您有一个名为 overlappedPtr 类型为 OVERLAPPED* 的指针 真的 指向 MYOVERLAPPED1,您可以这样做func1(unique_ptr&lt;MYOVERLAPPED1&gt;((MYOVERLAPPED1*)overlappedPtr);
      猜你喜欢
      • 2016-03-31
      • 2015-09-03
      • 2013-01-16
      • 2022-12-12
      • 2012-03-30
      • 1970-01-01
      • 2013-01-27
      • 2021-03-20
      • 1970-01-01
      相关资源
      最近更新 更多