C++基础知识:this指针、内联函数、构造函数及析构函数
this指针
this指针是类中成员函数的一个隐藏形参,哪个类对象调用成员函数,this指针就指向谁。
const 修饰指针:
int a = 10;
const int *p = &a; //const 修饰的是 *p ,不能通过p修改a的值
int const *p = &a; //const 修饰的是 *p ,不能通过p修改a的值
int * const p = &a; //const 修饰的是 p ,不能修改p的指向
const int * const p = &a; //指针的指向不能修改,也不能通过p修改a的值
this的类型:类名 * const this;
注意: 不能在成员函数的形参中使用this指针; 不能在构造函数的初始化表中使用this指针; 可以在成员函数的函数体中使用this指针。
使用场景
一、成员函数的形参名,和类的成员变量名冲突时。 ----也可以通过构造函数的初始化表解决
二、拷贝赋值函数,返回自身的引用时。
#include <iostream>
using namespace std;
class Stu{
private:
int a;
int* p;
public:
Stu(int a, int p){
this->a = a;
this->p = new int[p]{0};
}
void showInfo(){
cout << a << " " << *p << endl;
}
};
int main()
{
Stu stu(20, 30);
stu.showInfo();
return 0;
}
内联函数
内联函数其实就是在函数类型前加上 inline,其和C中的宏定义很像
不同点:
1.宏定义的替换是在预处理阶段完成的,内联函数是在编译阶段完成的;
2.内联函数也是函数,和函数的使用方式一样,也会做类型的检查, 而宏定义只是能完成简单的替换。
内联函数,保证了如同C中宏定义的高效性,同时避免出错,但同时内联也会造成:代码的膨胀。所以在C++中内联函数一般是简短的且调用次数多的函数,内联函数也不可以有延时或耗时操作,否则编译器会自动停止内联。
例子:
#include <iostream>
#define Min(a, b) (a < b ? a: b)
using namespace std;
inline int Max(int a, int b){
cout << "内联函数" << endl;
return a > b ? a: b;
}
int main()
{
int a = 10;
int b = 13;
cout << Min(a, b) << endl; //结果:10
cout << Max(a, b) << endl; //结果:13
return 0;
}
构造函数
其是一个特殊的函数,作用是对类中的属性进行初始化
格式:
函数名 + (形参列表) //函数名与类名相同,没有返回值,一般都是public权限
{
//初始化操作
}
另外构造函数又分:无参构造和有参构造,具体看形参列表有没有参数。
无参构造:形参列表内为空,编译器会默认提供
有参构造:当形参列表内有参数时,编译器不再默认提供
调用时机:
当类对象被定义时,编译器会自动调用与这个类的属性相对应的构造函数
在栈区或堆区定义,注意在堆区时,记得释放资源
构造函数的初始化列表:
可以在定义构造函数时,使用 冒号 的方式引出初始化表。
格式: 类名(构造函数的形参表):成员变量名1(初值1),成员变量名2(初值2)...
#include <iostream>
using namespace std;
class Stu{
private:
int a;
int* p;
public:
Stu():a(10), p(new int[32]{0}){ //形参表后加‘:’的方式引出初始化列表
// this->a = 10;
// this->p = new int[32]{0};
cout << "无参构造" << endl;
}
Stu(int a, int p){
this->a = a;
this->p = new int[p]{0};
cout << "有参构造" << endl;
}
void showInfo(){
cout << a << " " << *p << endl;
}
};
int main()
{
Stu stu; //无参构造
stu.showInfo();
Stu stu1(20, 30); //有参构造
stu1.showInfo();
return 0;
}
析构函数
其在对象消亡的时候,用来做释放空间等善后工作的。
格式:
~函数名 + (形参列表) //函数名与类名相同,没有返回值
{
//回收类中属性指向堆区的资源
//函数体
}
调用时机:
对象消亡,自动调用。
栈:生命周期结束时
堆:手动调用delete时
默认析构函数:
如果类中没有显性定义析构函数,编译器会默认提供一个函数体为空的 析构函数,用来消亡对象使用,如果显性定义了,默认的版本就不再提供了。
#include <iostream>
using namespace std;
class Stu{
private:
int a;
int* p;
public:
Stu(int a, int p){
this->a = a;
this->p = new int[p]{0};
cout << "有参构造" << endl;
}
~Stu(){
delete []p;
p = nullptr;
cout << "析造" << endl;
}
void showInfo(){
cout << a << " " << *p << endl;
}
};
int main()
{
Stu stu1(20, 30);
stu1.showInfo();
return 0;
}
构造函数和析构函数调用的顺序?
1.对于堆空间的对象,他们什么时候被消亡取决于什么时候delete, 先delete哪个,哪个就先消亡,所以,我们不考虑他的顺序。
2.对于栈空间的对象:----先构造的后析构
构造函数调用顺序:顺序调用
析构函数调用顺序:逆序调用