在operator=中使用Copy-and-Swap惯用法出现递归问题的排查
自定义MyVector模板类Copy-and-Swap惯用法递归问题排查与修复
问题概述
实现自定义模板类MyVector时,尝试用Copy-and-Swap惯用法实现赋值运算符,运行后出现递归行为,核心代码如下:
MyVector& operator= (const MyVector& v) { cout << "copy assignment operator" << endl; MyVector<int> copy = v; // copy and swap swap(*this, copy); return *this; }
问题原因分析
缺少自定义swap函数触发递归
没有为MyVector实现成员swap函数,调用swap(*this, copy)时会使用std::swap。而std::swap的默认实现依赖赋值运算符,会再次触发你的operator=调用,形成无限递归。模板类实例化硬编码错误
在模板类中创建拷贝对象时硬编码了MyVector<int>,应该使用模板参数T,否则当模板实例化类型不是int时会出现类型不匹配问题。拷贝构造函数未完成完整拷贝
当前拷贝构造函数仅复制了第一个元素*m_data = *v.m_data;,没有遍历所有元素,会导致数据丢失。
修复方案
1. 添加自定义swap成员函数
在MyVector类的public部分添加noexcept的swap函数,直接交换成员变量,避免调用赋值运算符:
void swap(MyVector& other) noexcept { using std::swap; swap(m_size, other.m_size); swap(m_capacity, other.m_capacity); swap(m_data, other.m_data); }
2. 修正赋值运算符实现
将硬编码的MyVector<int>改为MyVector<T>,并调用自定义的swap成员函数:
MyVector& operator= (const MyVector& v) { cout << "copy assignment operator" << endl; MyVector<T> copy(v); // 用模板参数创建拷贝对象 swap(copy); // 调用自定义swap,避免递归 return *this; }
3. 修复拷贝构造函数
修改拷贝构造函数,遍历复制所有元素:
MyVector(const MyVector& v) : m_size(v.m_size), m_capacity(v.m_capacity) { cout << "copy ctor" << endl; m_data = new T[m_size]; // 遍历复制每一个元素 for (int i = 0; i < m_size; ++i) { m_data[i] = v.m_data[i]; } }
进阶优化:统一赋值运算符
可以将拷贝赋值和移动赋值合并为一个统一的赋值运算符,利用值传递自动触发拷贝或移动构造,代码更简洁高效:
MyVector& operator= (MyVector other) // 值传递,自动选择拷贝/移动构造 { cout << "assignment operator" << endl; swap(other); return *this; }
内容的提问来源于stack exchange,提问作者KcFnMi
相关产品推荐
相关产品推荐

