千家信息网

C语言运算符的重载实例分析

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,本篇内容介绍了"C语言运算符的重载实例分析"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!写一个Add
千家信息网最后更新 2026年11月01日C语言运算符的重载实例分析

本篇内容介绍了"C语言运算符的重载实例分析"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

写一个Add函数

我们先讨论下面代码,并复习前面的内容

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));

通过返回对象,就可以实现连等;并且我们可以通过引用返回,因为此对象的生存期并不受函数的影响,不会产生一个临时对象作为一个过度

防止自赋值
若是我们将obja给obja赋值,也就是自赋值

obja = objaoperator=(&obja,obja);

我们就需要进行一步判断

Object& operator=(const Object& obj){        if(this != &obj)//防止自赋值        {                this->value = obj.value;        }        return *this;}

上面问题解决

我们通过这段代码来看,与上面问题相同

 Object& operator=(const Object& 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语言运算符的重载实例分析"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

函数 对象 地址 运算符 运算 分析 空间 这是 问题 编译 也就是 内容 加号 数据 编译器 运行 实例 实例分析 语言 有效 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 亿人帮互联网科技有限公司 互联网为科技 金融科技创新监管互联网金融 互联网科技英文 中国互联网科技发展 赫美联合互联网科技 盛创互联网科技有限公司 青海省互联网新科技 蓝色互联网科技 小米互联网科技园设置 互联网和黑科技的看法 本届互联网博览会上的黑科技 互联网数据科技专业 东营紫格互联网科技 广东鹅鹅鹅互联网科技有限公司 普陀区互联网教育科技管理办法 互联网科技收购价值 数字互联网科技有限公司 北京品多多互联网科技有限公司 科技互联网企业在行动 新华互联网科技学校 圆梦互联网科技 互联网科技上市公司 哈尔滨秒房互联网科技有限公司 互联网科技实习生岗位职责 中国互联网有什么科技含量 元气玛特互联网科技公司是外包吗 广州百诚互联网科技有限公司官网 深圳互联网科技园地址 知域互联网科技有限公司官网
0