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

关于隐式移动赋值运算符调用基类拷贝赋值运算符的规则确认

C++隐式移动操作的基类调用规则解析

示例代码

#include <string>

struct Base
{
    ~Base() = default;
    std::string strBase{ "Base"};
};

struct Derived : public Base
{
    std::string strDerived{ "Derived" };
};

int main()
{
    Derived a, b;
    a = std::move( b );
    return 0;
}

核心疑问

观察到示例中Derived的strDerived被移动,而基类Base的strBase被拷贝,需明确以下问题:

  • 遵循零规则的Derived的隐式声明移动赋值运算符,在基类Base无移动赋值运算符时,是否总会调用基类的隐式拷贝赋值运算符?是否有C++标准的明确保证?
  • 若将示例中的移动赋值替换为移动构造,情况是否相同?

标准规则与行为解释

1. 隐式移动赋值运算符的行为

根据C标准(C11及后续版本),当类的移动赋值运算符被隐式声明时:

  • 对于基类子对象:如果基类没有可访问的、未被删除的移动赋值运算符,则会调用基类的隐式(或显式)拷贝赋值运算符。
    示例中的Base因为声明了用户自定义析构函数(即使是=default),在C11中会导致隐式移动赋值运算符被删除;C17及以后虽放宽了规则,但Base仍未生成移动赋值运算符,因此Derived的隐式移动赋值会调用Base的拷贝赋值,导致strBase被拷贝。
  • 对于派生类的非静态成员:如果成员类型有可访问的移动赋值运算符(如std::string),则调用该成员的移动赋值,因此strDerived被移动。

这一行为是C++标准明确保证的。

2. 隐式移动构造函数的情况

替换为移动构造时,规则完全一致:

  • 隐式移动构造函数会先初始化基类子对象:如果基类没有可访问的、未被删除的移动构造函数,则调用基类的拷贝构造函数。
  • 派生类成员则会调用自身的移动构造函数(如std::string的移动构造)。

因此移动构造场景下,同样会出现基类成员被拷贝、派生类成员被移动的现象,这也是标准规定的行为。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 22:07:20