在自定义 class 中调用 a=s+b 导致 s(或 b)也受到影响(甚至当声明为常量时)
In custom class when calling a=s+b causing s (or b) also be effected (and even when declared as constant)
所以最近我正在使用我的自定义 class,当我执行算术运算时,它也会影响方程中的参数(因此当调用 auto a=s+b
时也会导致 s
正在改变)。即使我将这些变量声明为 const
并将参数全部传递给值(不是引用)。
所以这是我的 classes 代码的(部分):
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=(T *)calloc(dim, sizeof(T));
d=new T[dim];
copy(l.begin(), l.end(), d);
}
coord<T> operator+=(const coord<T> &r) {
//for(int i=0; i<(r.dim<this->dim?r.dim:this->dim); i++) {
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];
}
friend coord<T> operator+(coord<T> lhs, const coord<T> &r) { return lhs+=r; }
};
当我执行以下主要代码时:
int main() {
coord<double> s({3,2,3});
coord<double> b({3,2,3});
cout << s << endl;
auto a=s+b;
s+=b;
cout << s << endl << b << endl << a << endl;
return 0;
}
它给出了输出:
3, 2, 3
3, 2, 3
9, 6, 9
9, 6, 9
其中第一个是原来的s
,其他的分别是s
、b
和a
后的
然后我想也许我传递了一些东西作为参考,所以我回到代码并将所有内容更改为按值传递(现在只更改 + 操作)到以下代码:
coord<T> operator+=(coord<T> r) {
//for(int i=0; i<(r.dim<this->dim?r.dim:this->dim); i++) {
if(r.dim>this->dim) {
throw "Addition's rhs has larger Dimension than lhs.";
}
for(di i=0; i<r.dim; i++) { r[i]+=this->d[i]; }
return r;
}
friend coord<T> operator+(coord<T> lhs, const coord<T> r) { return lhs+=r; }
这次给了:
3, 2, 3
9, 6, 9
3, 2, 3
9, 6, 9
基本上我们可以假设加法运算会影响原始变量。但这不应该发生,因为我们按值而不是引用传递参数,那为什么呢?我该如何解决?
没有复制构造函数 and/or 复制赋值,所以当您复制 coord<T>
时,只会复制指针 d
,而不是 d
指向的内存到。这可以通过 constructor/assignment 或使用 std::vector
来解决,并让向量为您处理所有内存管理,正如有人指出的那样。使用 std::vector
附带了一堆您不需要的其他东西(例如坐标的尺寸永远不会改变)。像下面这样一个简单的构造函数和复制赋值就可以了。
coord(const coord<T> &other) : dim(other.dim) {
d = (T *)malloc(dim * sizeof(T));
memcpy(d, other.d, dim * sizeof(T));
}
coord<T> &operator=(const coord<T> &other) {
free(d);
dim = other.dim;
d = (T *)malloc(dim * sizeof(T));
memcpy(d, other.d, dim * sizeof(T));
}
所以最近我正在使用我的自定义 class,当我执行算术运算时,它也会影响方程中的参数(因此当调用 auto a=s+b
时也会导致 s
正在改变)。即使我将这些变量声明为 const
并将参数全部传递给值(不是引用)。
所以这是我的 classes 代码的(部分):
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=(T *)calloc(dim, sizeof(T));
d=new T[dim];
copy(l.begin(), l.end(), d);
}
coord<T> operator+=(const coord<T> &r) {
//for(int i=0; i<(r.dim<this->dim?r.dim:this->dim); i++) {
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];
}
friend coord<T> operator+(coord<T> lhs, const coord<T> &r) { return lhs+=r; }
};
当我执行以下主要代码时:
int main() {
coord<double> s({3,2,3});
coord<double> b({3,2,3});
cout << s << endl;
auto a=s+b;
s+=b;
cout << s << endl << b << endl << a << endl;
return 0;
}
它给出了输出:
3, 2, 3
3, 2, 3
9, 6, 9
9, 6, 9
其中第一个是原来的s
,其他的分别是s
、b
和a
后的
然后我想也许我传递了一些东西作为参考,所以我回到代码并将所有内容更改为按值传递(现在只更改 + 操作)到以下代码:
coord<T> operator+=(coord<T> r) {
//for(int i=0; i<(r.dim<this->dim?r.dim:this->dim); i++) {
if(r.dim>this->dim) {
throw "Addition's rhs has larger Dimension than lhs.";
}
for(di i=0; i<r.dim; i++) { r[i]+=this->d[i]; }
return r;
}
friend coord<T> operator+(coord<T> lhs, const coord<T> r) { return lhs+=r; }
这次给了:
3, 2, 3
9, 6, 9
3, 2, 3
9, 6, 9
基本上我们可以假设加法运算会影响原始变量。但这不应该发生,因为我们按值而不是引用传递参数,那为什么呢?我该如何解决?
没有复制构造函数 and/or 复制赋值,所以当您复制 coord<T>
时,只会复制指针 d
,而不是 d
指向的内存到。这可以通过 constructor/assignment 或使用 std::vector
来解决,并让向量为您处理所有内存管理,正如有人指出的那样。使用 std::vector
附带了一堆您不需要的其他东西(例如坐标的尺寸永远不会改变)。像下面这样一个简单的构造函数和复制赋值就可以了。
coord(const coord<T> &other) : dim(other.dim) {
d = (T *)malloc(dim * sizeof(T));
memcpy(d, other.d, dim * sizeof(T));
}
coord<T> &operator=(const coord<T> &other) {
free(d);
dim = other.dim;
d = (T *)malloc(dim * sizeof(T));
memcpy(d, other.d, dim * sizeof(T));
}