You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何带自定义删除器的unique_ptr移动赋值运算符被隐式删除?

带自定义删除器的std::unique_ptr移动赋值被隐式删除的原因

我定义了一个pod类型,想用带自定义删除器的std::unique_ptr传递句柄,但编译失败,提示移动赋值运算符被隐式删除。我有点困惑:我的删除器是POD类型,这类类型通常是不抛出异常的可移动赋值类型,应该符合std::unique_ptr移动赋值的要求才对?

代码示例

#include <memory_resource> 
#include <memory> 
#include <optional>
#include <string_view>
#include <vector>
#include <cstdio>
 
using allocator_t = std::pmr::polymorphic_allocator<std::byte>;

struct pod
{
    int a;
    bool b;
};


template <typename T>
struct allocator_delete
{
    auto operator()(T* p) -> void {
        allocator_.delete_object(p);
    }
    allocator_t allocator_;
};

using pod_handle_t = std::unique_ptr<pod, allocator_delete<pod>>;


struct msg_outbound_metainfo_t
{
    pod_handle_t msg_handle_;
};

int main()
{
    pod_handle_t ptr;

    std::vector<msg_outbound_metainfo_t> vec;

    auto& meta = vec.emplace_back();
    meta.msg_handle_ = std::move(ptr);
}

错误信息

<source>:41:37: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>& std::unique_ptr<_Tp, _Dp>::operator=(std::unique_ptr<_Tp, _Dp>&&) [with _Tp = pod; _Dp = allocator_delete<pod>]'
   41 |     meta.msg_handle_ = std::move(ptr);
      |                                     ^
In file included from /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/memory:76,
                 from <source>:2:
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/unique_ptr.h:406:19: note: 'std::unique_ptr<_Tp, _Dp>& std::unique_ptr<_Tp, _Dp>::operator=(std::unique_ptr<_Tp, _Dp>&&) [with _Tp = pod; _Dp = allocator_delete<pod>]' is implicitly deleted because the default definition would be ill-formed:
  406 |       unique_ptr& operator=(unique_ptr&&) = default;
      |                   ^~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/unique_ptr.h:406:19: error: use of deleted function 'std::__uniq_ptr_data<_Tp, _Dp, true, false>& std::__uniq_ptr_data<_Tp, _Dp, true, false>::operator=(std::__uniq_ptr_data<_Tp, _Dp, true, false>&&) [with _Tp = pod; _Dp = allocator_delete<pod>]'
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/unique_ptr.h:243:24: note: declared here
  243 |       __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete;
      |                        ^~~~~~~~

问题根源与解决方案

问题本质

问题出在std::pmr::polymorphic_allocator的移动赋值特性上——它的移动赋值运算符是有条件 noexcept的,并非无条件noexcept。而std::unique_ptr的默认移动赋值运算符要求删除器的移动赋值必须是无条件noexcept的,否则编译器会隐式删除unique_ptr的移动赋值。

你的allocator_delete包含allocator_t(即polymorphic_allocator),所以它的移动赋值运算符的noexcept属性继承自polymorphic_allocator的移动赋值,也就是有条件的,不满足unique_ptr的要求。

修复方案

显式声明allocator_delete的移动赋值为无条件noexcept即可:

template <typename T>
struct allocator_delete
{
    auto operator()(T* p) -> void {
        allocator_.delete_object(p);
    }

    // 显式声明移动赋值为无条件noexcept
    allocator_delete& operator=(allocator_delete&&) noexcept = default;

    allocator_t allocator_;
};

这样allocator_delete的移动赋值就满足了unique_ptr的要求,unique_ptr的默认移动赋值会正常生成,代码即可编译通过。

内容的提问来源于stack exchange,提问作者glades

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 02:35:22