C++基础篇:03 常函数、拷贝构造函数、赋值函数

1 常函数

        被const修饰过的成员函数,叫做常函数

        格式:

    int func(int num)const

        ① 已知通过对象调用成员函数时,编译器会自动把该对象的地址隐式传递给成员函数的this指针

        ② 如果对象被const修饰过,那么它的地址也带有const属性,就不能直接调用普通的成员函数了,编译器会报错,因此此时传递的对象地址是带有const属性,而普通成员函数的this指针默认不带const属性,C++编译器认为这个直接转换是非法的

        ③ 如果成员函数的this指针被const修饰后,就可以被const属性的对象调用,所以把普通成员函数定义为常函数,const本质上是修饰this指针

        ④ const属性的对象只能调用常函数,常函数也只能调用常函数

        ⑤ 构造函数不用,也大部分情况下不能设置为常函数

        ⑥ 同名的成员函数,如果其他的参数列表相同,但是常属性不同,也可以构成重载

        ⑦ 一般在常函数中,无法修改成员变量的值,但是在定义成员变量时,如果使用mutable来修饰,那么在常函数中也可以修改该成员变量的值

C语言和C++中的const有什么相同与不同?

相同:都是用来保护数据

不同:

        C++编译器会优化const变量的取值过程,哪怕通过指针强制修改const变量的内存数据,但是编译器也不会去重新读取内存,这样的机制更为安全

        C++中const修饰成员函数(修饰隐藏的this指针),定义常函数

一个空的结构体在C和C++中分别占多少字节?为什么?

        C:0字节,C++:1字节。在C++中,这个结构可以定义成员函数,并且默认有四个成员函数(构造、析构、拷贝构造、赋值),在创建结构变量时也会自动调用构造

        成员函数都自带一个隐藏的this指针参数,因此调用所有的成员函数都需要传递变量的地址

        因此,这样的机制就要求结构变量必须在内存中至少占用1字节以上的内存,才能传递地址给成员函数,所以当结构体中没有成员时,编译器为了能传递结构地址,会让结构拥有1字节。

2 拷贝构造函数

        拷贝构造是一种特殊的构造函数,无返回值,格式:类名(const 类名& that){}

        何时会使用拷贝对象?

        当时使用旧对象给新对象初始化时,会自动调用拷贝构造

    Data d;         //   无参构造
    Data d1 = d;    //  拷贝构造
    Data* d2 = new Data(d); //  拷贝构造
    void func(Data d){}
    func(d);        //  拷贝构造

        拷贝构造任务:

                顾名思义,拷贝构造负责把旧对象中的成员变量拷贝一份给新对象

                隐藏的自动生成的拷贝构造函数会具有给每个成员变量拷贝的功能

        拷贝构造函数什么情况需要显式实现

                普通情况下,编译器自动生成的拷贝构造完全够用,不需要显式实现,但是当类中的成员有指针且为该该指针分配堆内存时,默认的拷贝构造函数只会对指针的值进行拷贝,这样就导致两个对象的指针成员都指向同一块堆内存,平时执行会脏数据,一旦执行析构函数时,就会导致重复释放堆内存,导致内存崩溃,这就叫做浅拷贝。此时,就需要显式实现拷贝构造(进行深拷贝)避免此类情况

浅拷贝与深拷贝

        当类中有指针成员且为指针分配堆内存时,浅拷贝只会拷贝指针变量的值,深拷贝不拷贝指针变量的值,而是拷贝指针所指向内存的内容

3 赋值函数

        一个旧对象给另一个旧对象赋值(两个对象都已经创建完成)时调用的成员函数

        C++中把所有的运算符操作都当成函数处理,使用运算符时相当于在调用对应的运算符函数格式:类名的引用 operator=(const 类名& that){}

        使用条件:  

                Test t1,t2;//  无参构造

                t1=t2;  //  赋值操作函数  

        赋值操作函数的任务

        与拷贝构造基本一致,默认下编译器也会自动生成一个具有浅拷贝功能的赋值操作函数,一般情况够用,但是当需要深拷贝时,就需要显式实现拷贝构造函数以及赋值操作函数

实现赋值操作函数需要注意的问题    

        ① 两个旧对象都有旧内存,因此需要先释放被赋值对象的旧内存,然后被赋值者根据拷贝内容再重新申请新内存,把赋值者内存中的内容拷贝给被赋值者的内存中

        ② 可能出现对象自己给自己赋值,通过判断this指针与赋值者的地址是否相同来决定是否执行赋值操作

        ③ 赋值运算符可以连续赋值,赋值操作函数的返回值类型为类类型的引用,才能连续赋值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

就酱77叭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值