剑指offer 读书笔记——第2章

剑指offer 读书笔记——第2章

感觉自己的代码能力还在很弱,所以又第二遍仔细的阅读剑指offer了

第二章 面试需要的基础知识

面试题1 赋值运算函数

所谓赋值运算函数就是对=这个操作符进行重载,从而使等号能够直接用于两个实例之间的赋值。这个C++课上学过,不过现在忘完了,只记得学过。

经典解法

需要考虑的点

  1. 返回值的类型声明为该类型的引用,在函数结束前返回实例自身的引用(*this)。只有返回一个引用,才可以连续赋值。object1=object2=object3就是连续赋值。赋值采用右结合律,从最右边开始计算。不然的话当首先执行完object2=object3 后,object2 虽然自己的成员已经得到了更改,但是它不能再作为object1=object2 这个等号的右值,因为在前一个=的执行中,它没有获得返回值。而返回对象的话,就需要重新执行新建一个对象和销毁对象的构造与析构操作,增加不必要开销,降低赋值函数的效率。
  2. 传入的参数申明为常量引用
  3. 释放实例自身已有的内存
  4. 判断传入参数是否和当前的实例相同,相同的话不进行赋值操作,直接返回实例。

代码:初级版

CMyString& CMyString::operator = (const CMyString& str)
{
    if(this == &str)
        return *this;

    delete []m_pData;
    m_pData = nullptr;

    m_pData = new char[strlen(str.m_pData) + 1]; //给strcpy复制的字符串申请空间
    strcpy(m_pData, str.m_pData);

    return *this;
}

代码:高级版

CMyString& CMyString::operator = (const CMyString& str)
{
    if(this != &str){
    	CMyString strTemp(str);   // 新建一个实例 
        
        char *pTemp=strTemp.m_pData;   // 新建一个临时指针保存数据
        strTemp.m_pData = m_pData; 		// 交换
        m_pData = pTemp;
    }
    return *this;
}

初级版在使用new分配内存的时候,已经把原来的数据给清楚了(delete []m_pData;),这时在新分配内存的时候,如果内存不足会导致new char抛出异常,使得m_pData 变成一个空指针,这样很容易导致程序崩溃。因为在抛出异常之后,原来的CMyString实例因为数据被delete了,所以不再保持有效的状态,违背了异常安全性的原则。 (可以先将原来的数据备份,等new 成功了,再将原来的数据delete给释放掉)

代码思路:新建一个实例,新建一个临时指针从而用于数据交换。

tmp    tmp
^       |
|       
str<--this 
先将str的值备份到tmp中,然后将str的值更新为this的值,然后在把this的值更新为tmp的值
两个数据的交换必然需要新建第三个变量来存放其中一个变量的值。

之所以需要新建一个实例是因为实例是个临时变量,所以完成操作后会自动释放掉他的数据,也就是原来的数据。

指针与引用的异同

常量指针与常量引用。

对于引用只有两种描述:

// 对常量类型的引用  
const type &ref = type a;
//对变量类型的引用
type &ref = type a;

对常量类型的引用 实际上既可以对常量类型引用,也可以对变量类型引用,但是不能通过引用来修改它引用的对象。

对于指针的修饰有4种:

// 普通的指针 poi is a pointer point to a type  ,
//指针的值(指向的地址,可以改变),被指向的变量的值也可以改变
type *poi;

//常量指针 poi is a const pointer point to a type 
//指针的值(指向的地址)不能改变,被指向的变量的值可以改变
type *const poi;

// poi is a pointer point to a const type
//指针的值(指向的地址)可以改变,所以指针可以指向其他变量,
//被指向的变量的值不可以改变,所以指针不能修改指向的变量的值,
const type *poi;

// poi is a const pointer point to a const type
// 指针的值(指向的地址)不能改变,所以指针不能指向其他变量,
//被指向的变量的不可以改变,所以指针不能修改指向的变量的值
const type *const poi;

以* &作为分割符进行读取,const作为前缀修饰的对象,对象存储的值不变。

对于指向const type 的指针或者引用而言,指向的(引用的)变量类型不一定是常量,但是无法通过指针或者引用来修改其指向的(引用的)变量的值。《C++primer》中所说:所谓指向常量的指针或引用,不过是指针自以为自己指向了一个常量,所以自觉地不去改变所指对象的值。

疑惑

  1. 为什么申明的返回值是引用,而返回的却是指针?
    • 引用是地址的别名,但是不分配内存空间。 CMyString &A= *this 这里*this是指向CMyString这个类的实例的地址,而A是CMyString的一个实例的引用,是引用就需要与这个实例的内存地址相关联,所以可以传入 *this ,也就是实例的地址。 本来 =号用于赋值的时候,左值是地址,右值是变量地址上的数据也就是变量的值,但是引用的=号的右值是变量的地址。所以可以传入地址,也就是指针。
  2. 传入的参数是个常量引用,为什么不使用常量指针: const CMyString *str
    • 虽然const CMyString *strcongst CMyString &str 都不能去修改实参的值了,但是引用不是对象,是不分配内存的啊,使用指针的话,肯定会占用内存,然后不用的时候销毁内存,所以效率会降低。而且引用是一定不会空的,所以不用考虑所指的对象是否为空。(提升效率的关键,可以不申请内存就不申请内存,因为不管是自己去释放,还是系统自动回收,分配和回收都会带来效率的下降。所以能用指针就用指针,能用引用就用引用,最坏的情况才是值拷贝。)( 对象是指一块能存储数据并具有某种类型的内存空间)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值