std::move结合多态移动赋值运算符的内存安全问题
结论
你写的Child类移动赋值运算符内,先调用父类移动赋值、再移动子类成员str3_的两行逻辑完全内存安全,没有内存违规风险。
原理说明
- 调用父类移动赋值时不会移动整个子类对象。执行
Parent::operator=(std::move(other))时,std::move(other)生成的Child类型右值会隐式转换为绑定到other内部Parent基类子对象的Parent&&右值引用,这个引用从类型层面就只能访问Parent类定义的成员,根本碰不到Child独有的str3_。 - 父类移动赋值的作用范围严格限定在基类子对象。Parent的移动赋值运算符是Parent的成员函数,内部逻辑仅移动Parent自身的
str1_、str2_两个成员,它感知不到Child类的存在,也没有途径访问或修改Child的派生部分成员。这行调用执行完成后,other的str3_成员没有被任何操作改动,后续对str3_做移动赋值完全合法。 - 代码中的自赋值检查逻辑可以正常生效。无论是Child层还是Parent层的
if (this == &other)判断,在自赋值场景下都能正确识别同一对象,不会出现重复移动自身成员的问题。
误区提醒
不要把调用父类移动赋值的操作和内存级整块对象移动混淆。C继承体系下,基类成员函数默认只处理当前类对应的子对象部分,只有显式使用
memcpy/memmove做整块内存覆盖、或者父类移动赋值被错误实现为越界操作时才会触发内存问题。你给出的示例里,父类移动赋值仅对自身的std::string成员调用标准库的移动赋值,完全符合C对象模型的安全要求。
class Parent { public: // Constructors Parent& operator=(Parent&& other) noexcept { if (this == &other) return *this; str1_ = std::move(other.str1_); str2_ = std::move(other.str2_); return *this; } protected: std::string str1_, str2_; }; class Child : public Parent { public: // Constructors Child& operator=(Child&& other) noexcept { if (this == &other) return *this; // 以下两行逻辑内存安全 Parent::operator=(std::move(other)); str3_ = std::move(other.str3_); return *this; } private: std::string str3_; };
内容的提问来源于stack exchange,提问作者Drake Johnson
相关产品推荐
相关产品推荐

