我们先讨论下面代码,并复习前面的内容
class complex{private:double real, image;public:complex() :real(0), image(0) {}complex(double r, double i) :real(r), image(i) {}~complex() {}//complex add(const complex* const this,const complex &c)complex add(const complex& x)const{complex y;y.real = real + x.real;y.image = image + x.image;return y;//return complex(this->real + x.real, this->image + x.image);}void print(){cout << real << "+" << image << "i" << endl;}};int main(){complex c1(12, 23);complex c2(4.5, 5.6);complex c3;c3 = c1.add(c2);c3.print();return 0;}
直接return可以使用无名函数直接代替将亡值对象,相比可以省一次对象的构建
我们再分析如果我们使用引用返回add函数
const complex& add(const complex& x)const{complex y;y.real = real + x.real;y.image = image + x.image;return y;//return complex(this->real + x.real, this->image + x.image);}
若我们以引用返回,将亡值对象会创建在add函数的栈帧中,然后返回将亡值地址,函数return结束该空间会被释放、
若没有引用,构建无名对象也就是将亡值对象会构建在主函数的空间中,这里使用将亡值对象值给到c3是没有问题的
我们查看对象的构造与析构
class complex{private:double real, image;public:complex() :real(0), image(0) {}complex(double r, double i) :real(r), image(i) { cout << "create:" << this << endl; }complex(const complex& x):real(x.real),image(x.image){cout << "copy create:" << this << endl;}~complex(){cout << "~complex:" << this << endl;}//complex add(const complex* const this,const complex &c)complex add(const complex& x)const{return complex(this->real + x.real, this->image + x.image);}void print(){祝你一路顺风歌词cout << real << "+" << image 关于学习的电影<< "i" << endl;}};int main(){complex c1(12, 23);complex c2(4.5, 5.6);complex c3;c3 = c1.add(c2);c3.print();return 0;}
首先我们使用引用返回需要加上const修饰,这是因为我们返回将亡值在临时空间具有常性,所以普通引用是不能进行返回的,需要使用常引用返回
const complex& add(const complex& x)const{return complex(this->real + x.real, this->image + x.image);}
我们发现对临时对象的构建后马上就进行析构,那么是怎么将数据拿出给到c3的?这个在最后我们进行分析
//complex operator+(const complex* const this,const complex &c)complex operator+(const complex &c) const{return complex(this->real + x.real, this->image + x.image);}
这里是不可以的,加号是一个操作符,不能使用操作放作为有效的函数名称;但是在c++中为了使这些操作符号能够当作函数名,那么我们需要在前面加上一个关键字operator
//complex operator+(const complex* const this,const complex &c)complex operator+(const complex &c) const{return complex(this->real + x.real, this->image + x.image);}
也就是告诉编译器,加号是一个有效的函数名,这就叫做运算符的重载;随后我们之间使用 c3 = c1 + c2 就是可以的
int main(){complex c1(12, 23);complex c2(4.5, 5.6);complex c3;c3 = c1 + c2;//编译器编译会是下面的情况//c3 = c1.operator+(c2);//c3 = operator+(&c1,c2); 加上this指针}
一个对象,编译器会给它有6个缺省函数
我们再来看下面这个问题
//我们写一个赋值运算符重载void operator=(const object& obj){this->value = obj.value;}//返回类型为void,这样不可以就不可以连等//obja = objb = objc;//obja = objb.operator=(objc);//obja = operator=(&objb,objc); 返回的无类型,不能给obja赋值
且赋值函数不可以定义为const修饰
object& operator=(const object& obj){this->value = obj.value;return *this;}
obja = objb = objc;//改写obja = objb.operator=(objc);obja = operator=(&objb,objc);obja.operator=(operator=(&objb,objc));operator=(&obja,operator=(&objb,objc));
通过返回对象,就可以实现连等方大同 nothing;并且我们可以通过引用返回,因为此对象的生存期并不受函数的影响,不会产生一个临时对象作为一个过度
防止自赋值
若是我们将obja给obja赋值,也就是自赋值
obja = objaoperator=(&obja,obja);
我们就需要进行一步判断
object& operator=(const object& obj){if(this != &obj)//防止自赋值{this->value = obj.value;}return *this;}
我们通过这段代码来看,与上面问题相同
object& operator=(const o2019国庆晚会bject& obj){if (this != &obj){this->value = obj.value;}return *this;}};object& fun(const object& obj){int val = obj.value() + 10;object obja(val);return obja;}int main(){object objx(0);object objy(0);objy = fun(objx);cout << objy.value() << endl;return 0;}
我们在这里希望通过引用返回,这里return的临时对象会构建在fun函数的栈帧中,并且在函数结束栈帧释放,随后调用赋值运算符重载,但是数值依旧是正确的
我们跟踪这个被析构对象的地址,首先我们过年的音乐定位在fun函数的return obja;
,随后进入析构函数将我们的obja进行析构
接着运行到回到主函数进行赋值,接着进入赋值运算符重载,可以看到,这里的obj地址与已被析构的obja地址相同
可以看到这个值依旧存在,依旧可以打印给出,这是因为vs2019的特殊性质造成的;我们每次运行程序会发现每次的对象地址都在变化,逻辑地址会随机改变,被析构对象的栈帧不会被接下来的赋值运算符重载扰乱地址空间,所以即使我们引用返回的对象已经死亡依旧可以将数值正确返回
但是在vc中,我们得到的值会是随机值,这是因为vc中每次运行程序地址都不会改变,当我们从fun函数退出进入赋值语句中,就会将原本存储数据的地址扰乱,继而变成了随机值
尽管我们引用返回能够将数据正确打印,但是该对象已经死亡,这是不安全的,所以我们一定不要以引用返回对象
vs2019具有一个特点:当我们调用函数,若函数中没有定义局部变量或局部对象时,该函数基本不对栈帧进行清扫
到此这篇关于c语言运算符的重载详解的文章就介绍到这了,更多相关c语言运算符重载内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!
本文发布于:2023-04-04 16:13:12,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/a32808f5cb664bdd015ea2d23535a9a8.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:C语言运算符的重载详解.doc
本文 PDF 下载地址:C语言运算符的重载详解.pdf
留言与评论(共有 0 条评论) |