如何解决重载运算符+在C ++中添加两个数组
任务是重载运算符+,以便添加两个数组。数组是一个具有两个私有成员的类,它们具有int *数据和int m(数组的容量)。
void Array::setM(int m){
this->m = m;
this->data = new int[this->m];
}
int& Array::operator[](int i){
return this->data[i];
}
Array& Array::operator+(Array& a){
Array res;
if (this->m >= a.m) {
res.setM(this->m);
for (int i=0; i<this->m; i++){
res.data[i] = this->data[i] + a.data[i];
}
}
else if (this->m < a.m) {
res.setM(a.m);
for (int i=0; i<a.m; i++){
res.data[i] = this->data[i] + a.data[i];
}
}
Array& rez = res;
return rez;
}
这是主要的:
int main()
{
Array a(3);
Array& a1 = a;
a1[0] = 1;
a1[1] = 2;
a1[2] = 4;
Array b(3);
Array& b1 = b;
b1[0] = 1;
b1[1] = 2;
b1[2] = 4;
Array& c = a1.operator+(b1);
for (int i=0; i<3; i++){
cout<<c[i]<<" ";
}
return 0;
}
该函数在返回类型为Array时工作正常,但在返回类型为Array&时返回173104 42007364200896。我从c ++开始,所以引用有点让我感到困惑,我看不到函数返回参考点类型?
解决方法
让我们逐步考虑您的运营商实施。
对于初学者,操作员内部的右操作数不变。所以该函数至少应声明为
Array& operator+( const Array& a );
该函数在其主体内创建Array
类型的新对象。
Array res;
因此,由于对象是函数的局部变量,因此您可能不会返回对其的引用。这意味着应将运算符声明为
Array operator+( const Array& a );
或
const Array operator+( const Array& a );
此代码段
if (this->m >= a.m) {
res.setM(this->m);
for (int i=0; i<this->m; i++){
res.data[i] = this->data[i] + a.data[i];
}
}
当a.m
小于this->m
时可以调用未定义的行为。
由于成员函数不会更改左操作数,因此该函数应为常量成员函数。
const Array operator +( const Array& a ) const;
通常,此类运算符被声明为类的单独的好友函数。
friend const Array operator+( const Array &a,const Array &b );
考虑到您可以在运算符中使用的算法,可以按照以下方式进行定义(在类定义之外。或者,如果您想在类定义中定义它,那么您需要使用指定者朋友)>
const Array operator+( const Array &a,const Array &b )
{
int m = std::min( a.m,b.m );
Array res( m );
for ( int i = 0; i < m; i++ )
{
res.data[i] = a.data[i] + b.data[i];
}
return res;
}
请注意,函数setM
会产生内存泄漏,因为它不会删除类型为Array
的对象的早期分配的内存
void Array::setM(int m){
this->m = m;
this->data = new int[this->m];
}
该功能不安全。
还请记住,带有参数的构造函数应使用函数说明符explicit
声明。否则,您会遇到整数到类型Array
的意外转换。
在动态分配数组时,您需要至少显式地编写析构函数,复制构造函数和复制赋值运算符。
,您在这里违反规则,得到了未定义行为。您的程序可能由于分段错误而崩溃,或者可能像您观察到的那样输出垃圾。
您看到的是,您正在返回对局部变量的引用。不是很好。让我解释一下。
您在函数内部声明的变量通常具有自动存储功能。这意味着它们具有明确定义的存在开始(声明)和存在结束(即范围的结束)。就您而言,这是函数的结尾:
Array& Array::operator+(Array& a) {
Array res;
if (this->m >= a.m) {
res.setM(this->m);
for (int i=0; i<this->m; i++){
res.data[i] = this->data[i] + a.data[i];
}
} else if (this->m < a.m) {
res.setM(a.m);
for (int i = 0; i < a.m; i++) {
res.data[i] = this->data[i] + a.data[i];
} // <-- here,`i` dies.
}
Array& rez = res;
return rez;
} // <-- here,`res` dies.
因此,引用rez
指向无效变量。读取它被标准归为未定义行为。
显而易见的解决方案是按值返回,并且还应该对参数使用const引用:
Array Array::operator+(Array const& a) {
Array res;
// [...]
return res;
}
在这种情况下,编译器将复制(或移动)res
对象。请记住,编译器确实非常擅长工作,并且在这种特殊情况下很可能会应用复制省略。这意味着将没有副本,变量res
将直接在返回通道中构造。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。