java赋值运算符题目_《剑指Offer》面试题1:赋值运算符函数

《剑指Offer——名企面试官精讲典型编程题》

作者:何海涛

一、书上原题再现

面试题1:赋值运算符函数

题目:如下为类型CMyString的声明,请为该类型添加赋值运算符函数。

class CMyString

{

public:

CMyString(char* pData = nullptr);

CMyString(const CMyString& str);

~CMyString(void);

void Print();

private:

char* m_pData;

};

二、涉及的知识点

b358ecd13194994afc5fa47042193b48.png

三、解题过程

赋值:

int a;  //声明

a = 10; //赋值

运算符:

+ - * / = % < > ?: 等等

赋值运算符:

=

赋值运算符函数:

What?嗯?

其实,这里涉及到了运算符重载的知识点。我一个遨游在Java大海里的浪子,突然灌一口C/C++的海水,感觉有点生涩。

什么是运算符重载?

简单讲,比如说:

+ 加号的本意是   1+1 = 2  在这里是 累加 的功能

在类似于Java、Python这类高级语言中,当 + 加号 出现在字符串之间比如 "Hello" + "World !",那么这里的加号就会被用来实现 连接两个字符串 的功能。

加号不干 累加 的功能,而是实现了 连接两个字符串 的功能,这就叫做 加法运算符的重载。

运算符重载中有一点要求需要特别注意:重载运算符的参数至少应有一个是类对象(或类对象的引用)

也就是说,参数不能全部是C++的基本类型,以防止用户修改用于基本类型数据成员的运算符的性质,如下面这样是不对的:

int operator + (int a,int b)

{

return(a-b);

}

原来运算符+的作用是对两个数相加,现在企图通过重载使它的作用改为两个数相减。

如果允许这样重载的话,那么表达式4+3,它的结果是7还是1呢?显然,这是绝对要禁止的。

Java八大基本数据类型:

byte   short        int          long

float   double     boolean         char

基本数据类型是没有String的,String的本质是一个用户类。所以说当加号出现在两个字符串之间的时候,实现连接两个字符串这个功能是加法运算符的重载。

但是,但是,但是,Java语言没有运算符重载:

Java doesn’t support user-defined operator overloading.

Java不支持用户自定义操作符重载。

The preferred approach is to define a method on your class to perform the action: a.add(b) instead of a + b.

首选的方法是在类中定义一个方法来实现这个功能,比如说通过 a.add(b) 来实现 a+b 的功能。

The only aspect of Java which comes close to “custom” operator overloading is the handling of + for strings,

Java唯一接近“自定义”运算符重载的方面是 + 用于字符串的处理,

which either results in compile-time concatenation of constants or execution-time concatenation using StringBuilder/StringBuffer.

这里的加法会造成在编译期或执行期使用StringBuilder/StringBuffer。

那么回到正题,这道题用的语言是C++,C++是有运算符重载的,给一个类添加赋值运算符函数。这个类就是一个字符串类,名为:CMyString

赋值运算符函数,就是重载赋值运算符了。下面是该函数的声明:

CMyString& operator = (const CMyString& str);

CMyString& 是函数的类型   operator = 整体看成函数名 const CMyString&是参数的类型 str 是参数的引用名

我们要做的就是书写函数体。

初级程序员版:

1     CMyString& operator = (const CMyString& str){

2            if(this == &str){

3                   return *this;

4            }else{

5                   delete []m_pData;

6                   m_pData = NULL;

7                   m_pData = new char[strlen(str.m_pData)+];

8                   strcpy(m_pData, str.m_pData);

9                   return *this;

10          }

11   }

这一版本的Bug之处就在于,假如第5、6行代码执行完成之后,第7行代码在分配内存的时候,分配失败了,那么我原先的数据也就没有了。

这样原先的对象就会成为一个空指针,想象一下,一个空指针在程序中,一旦程序后文又用到这个对象,那么这个程序极有可能崩溃!!!

考虑到异常安全性,下面的代码是

高级程序员版:

1     CMyString& operator = (const CMyString& str){

2            if(this == &str){

3                   return *this;

4            }else{

5                   CMyString strTemp(str);

6                   char* pTemp = strTemp.m_pData;

7                   strTemp.m_pData = m_pData;

8                   m_pData = pTemp;

9                   return *this;

10          }

11   }

四、调试步骤

使用DevC++进行调试

5904467196ebe68515be4fd4ea4d19b5.png

五、总结

不理解的地方:

CMyString strTemp(str);  看不懂这句代码,这句代码怎么就创建一个临时对象了,

这难道不是 类型名   函数名  参数?如果是这样的话,那么这个函数连声明都没有直接就用了?

既然临时对象一但运行结束就会被析构,那么为什么要进行交换?直接把临时对象的值赋值给当前对象的值不就行了?

一行代码

m_pData = strTemp.m_pData

不比三行代码强吗?

如果是说不能这样直接进行赋值,需要有个 char* pTemp的中间变量,那也应该是

两行代码:

char* pTemp = strTemp.m_pData;

//            strTemp.m_pData = m_pData;

m_pData = pTemp;

中间那行代码的意义何在,难不成是写交换算法写顺手了???

百思不得其姐......(所以我现在还不是高级程序员......)

总结:

1、 C++中通过运算符函数(关键字operator)可以对运算符进行重载;

2、如果要为一个类写赋值运算符函数,需要考虑内存分配失败的异常情况下要原对象不能为空指针的情况;

3、 一个对象的值,可以在创建的时候通过构造函数进行赋值,

也可以把另一个对象的值通过赋值运算符赋值给当前对象,

也可以通过赋值运算符进行多个对象的连续赋值,

这,就是赋值运算符函数的意义;

4、C++很飘逸,很成功,很失败,临时对象很难懂;

5、这道题的精髓我认为是就两点:

一是如何把这个operator = 函数完整的写出来,

二是在写的过程需要考虑内存泄漏的情况。

六、声明与致谢

参考文章:(每篇文章我都会去点赞

c865facb27b9b43ea7334fb779585d03.png,好的文章就应该公诸于世,大家共同学习)

博客园:

RUNOOB:

CSDN:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值