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

定义自定义析构函数的C++类为何仍满足std::movable约束

问题原因分析

核心误区

你对「用户自定义析构会抑制移动操作生成」的C++规则理解正确,但对std::movable约束的定义存在误解,这是编译失败的根本原因。

std::movable的官方定义

C++20中std::movable<T>的等价判断逻辑如下:

template<class T>
concept movable =
  std::is_object_v<T> &&
  std::is_move_constructible_v<T> &&
  std::is_assignable_v<T&, T&&> &&
  std::is_swappable_v<T>;

其中最容易被忽略的特性是:当类没有可用的移动构造/移动赋值时,只要拷贝构造/拷贝赋值可用,右值参数可以匹配到拷贝操作的const T&形参,此时std::is_move_constructible_v<T>和std::is_assignable_v<T&, T&&>仍会返回true。

代码不符合约束的原因

你的两个版本的Widget类都符合以下特性:

  • 用户声明了析构函数,编译器不会自动生成移动构造、移动赋值运算符
  • 编译器仍会隐式生成默认的拷贝构造、拷贝赋值运算符(该特性从C++11起已被标记为弃用,但仍符合标准兼容要求)

因此std::movable<Widget>的判断结果为true,你定义的!std::movable<T>约束自然不满足,触发编译错误。

解决方案

如果你希望Widget满足!std::movable<T>约束,需要显式删除拷贝构造和拷贝赋值运算符,此时类既不能拷贝也不能移动,即可符合约束要求:

struct Widget 
{
  ~Widget() = default;
  Widget(const Widget&) = delete;
  Widget& operator=(const Widget&) = delete;
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 08:18:02