C++同对象拷贝赋值疑问:remove_from_Folders为何不影响rhs.folders?
《C++ Primer》Message类拷贝赋值运算符自赋值问题解析
核心结论:编译器没有特殊规则,代码能运行是因为自赋值的执行流程恰好达成了(或看起来达成了)合理状态,本质需看remove_from_Folders()的具体实现
拆解
remove_from_Folders()的作用
原书里该函数的核心逻辑是遍历当前Message的folders集合,让每个关联的Folder对象将此Message从自身的消息列表中移除。是否清空Message自己的folders容器,是关键分歧点:若仅让
Folder移除Message,不清空folders
自赋值时,rhs就是当前对象的引用:- 调用
remove_from_Folders():Message从所有Folder中移除,但自身folders仍保留原Folder指针集合。 - 执行
folders = rhs.folders:因rhs是自己,相当于容器自我赋值,内容不变。 - 调用
add_to_Folders(rhs):遍历folders,将Message重新添加到所有Folder的消息列表。
最终Message的状态和自赋值前完全一致,所以代码表现正常。
- 调用
若既让
Folder移除Message,又清空folders
自赋值时流程会导致异常:remove_from_Folders()执行后,Message脱离所有Folder,且自身folders为空。folders = rhs.folders:rhs.folders已为空,赋值后folders仍为空。add_to_Folders(rhs)遍历空集合,无任何操作。
此时Message已不属于任何Folder,状态被修改——若你觉得“正常运行”,大概率是测试时仅检查了Message的内容,未验证Folder的关联关系。
编译器无特殊处理
自赋值完全遵循C++引用与运算符重载的常规规则,编译器不会对赋值运算符做额外的逻辑干预。部分场景下的“正常运行”,要么是流程抵消了影响,要么是测试覆盖不全。标准写法需加入自赋值判断
为避免无用操作与潜在逻辑错误,规范的拷贝赋值运算符应先判断是否为自赋值:Message& Message::operator=(const Message& rhs) { if (this != &rhs) { remove_from_Folders(); contents = rhs.contents; folders = rhs.folders; add_to_Folders(rhs); } return *this; }
内容的提问来源于stack exchange,提问作者J.Doe
相关产品推荐
相关产品推荐

