C++自定义coord类执行算术操作时原变量被修改的问题排查
问题根源
你的coord类包含原始堆指针成员T *d,但没有显式定义拷贝构造函数、拷贝赋值运算符,C++自动生成的默认拷贝逻辑是浅拷贝:只会复制指针本身的地址值,不会复制指针指向的堆内存内容。
当你按值传递coord对象时,新生成的副本和原对象会共享同一块d指向的堆内存,修改副本的d数组内容等价于直接修改原对象的内存数据,这就是你即使按值传递也会修改原变量的核心原因。
你后续修改的问题
你调整operator+=的写法不符合C++运算符重载的通用语义:
- 标准
+=运算符的作用是修改当前对象本身,返回当前对象的引用,支持链式调用(如a += b += c) - 你修改后的
operator+=反而修改参数r、返回r,完全违背了+=的设计逻辑,会引发更多语义错误。
修复方案
方案1:手动实现深拷贝逻辑(遵守三五法则)
给coord类补充析构函数、拷贝构造函数、拷贝赋值运算符,实现完整的深拷贝逻辑:
template<typename T> struct coord { T *d; long unsigned int dim; // 原有构造函数保持不变 coord(di dim, T val=0.0): dim(dim) { d=new T[dim]; for(di i=0;i<dim;i++) { d[i]=val; } } coord(initializer_list<T> l): dim{l.size()} { d=new T[dim]; copy(l.begin(), l.end(), d); } // 新增:析构函数释放内存 ~coord() { delete[] d; } // 新增:拷贝构造函数(深拷贝) coord(const coord<T>& other): dim(other.dim) { d = new T[dim]; for (di i = 0; i < dim; i++) { d[i] = other.d[i]; } } // 新增:拷贝赋值运算符(深拷贝,处理自赋值) coord<T>& operator=(const coord<T>& other) { if (this == &other) return *this; delete[] d; dim = other.dim; d = new T[dim]; for (di i = 0; i < dim; i++) { d[i] = other.d[i]; } return *this; } // 改回原有的正确operator+=逻辑,返回引用 coord<T>& operator+=(const coord<T> &r) { if(r.dim>this->dim) { throw "Addition's rhs has larger Dimension than lhs."; } for(di i=0; i<r.dim; i++) { this->d[i]+=r[i]; } return *this; } // 原有[]运算符重载保持不变 T& operator[](int i) { return d[i]; } T operator[](int i) const { return d[i]; } // operator+保持原有逻辑即可,现在传值的lhs是深拷贝副本,不会修改原对象 friend coord<T> operator+(coord<T> lhs, const coord<T> &r) { return lhs+=r; } };
方案2:用标准容器代替裸指针(更推荐,无手动内存管理风险)
直接把原始指针T *d替换为std::vector<T>,标准容器已经内置了正确的深拷贝、内存释放逻辑,你不需要手动写任何拷贝、析构代码:
#include <vector> template<typename T> struct coord { std::vector<T> d; long unsigned int dim() const { return d.size(); } // 直接用vector的size即可 coord(di dim, T val=0.0): d(dim, val) {} coord(initializer_list<T> l): d(l) {} coord<T>& operator+=(const coord<T> &r) { if(r.dim()>this->dim()) { throw "Addition's rhs has larger Dimension than lhs."; } for(di i=0; i<r.dim(); i++) { d[i]+=r.d[i]; } return *this; } T& operator[](int i) { return d[i]; } T operator[](int i) const { return d[i]; } friend coord<T> operator+(coord<T> lhs, const coord<T> &r) { return lhs+=r; } };
这个方案完全避免了手动内存管理的漏洞,代码更简洁,出错概率极低。
内容的提问来源于stack exchange,提问作者Andrew.Wolphoe
相关产品推荐
相关产品推荐

