内联函数
遇到函数体量小,但运行次数多时:
c语言:使用宏函数,替换以减少栈帧
C++:使用内联函数 没有压栈
宏函数:(在预处理时直接替换)
#define ADD(a,b) ((a)+(b))
1.内联函数
inline 符合条件 的情况下在调用的地方展开
inline int Add(int x,int y)
{
return x+y;
}
inline是一种以空间换时间的做法,省区调用函数额开销。如果函数体内比较长/递归等等,编译器优化时会忽略掉内联,因为展开导致编译出来的可执行程序变大。
不建议声明和定义分离,会导致链接错误。
内联函数仅是一种建议,需要看此函数是否能够成为内联函数.
由于内联函数是在调用的地方展开,所以不会进入符号表.在不同源文件中可以又多个名字相同但实现不同的内联函数.
auto
自动推导类型
int a=10;
auto b=a; b的类型自动识别类型为int;
auto* b 强调一定要传指针给b
auto&c 强调c是别名
int main()
{
int a[]={1,2,3,4,5,6}'
for(auto e:a)//这里e是a的形参
{
cout<<e<<" ":
}
cout<<endl;
for(auto& e:a)//这里e是a的引用
{
e--;
}
return 0;
}
范围for 自动依次取a的数据 赋值给e 自动给迭代 自动判断结束
注意
1.不能 auto a=1,b=4.0
2.不能做函数的参数 void Auto(auto a) {}
3.不能直接用来声明数组 autob[]={4,5,6};
指针空值
int* ptr=nullptr;
类与对象
C++兼容c struct 语法 同时将struct升级成了类。
类里面有 成员变量,成员函数。 可以在“结构体”里面直接写初始化等函数
struct Stack
{
void Init()
{
}
void Pop()
{
}
int* a;
int top;
int capacity;
}
int main()
{
struct Stack st1;
st1.Init();
st1.Push();
}
C++定义结构 类名就是类型
struct ListNode
{
ListNode* next;
int val;
};
但是C++定义中更喜欢用class来代替
class className
{
};
访问限定符
分为public protected private
限制的是类限定域以外的调用。
class的默认访问权限为private 不能使用 需要表明 public
struct默认为pubilc
class Stack
{
public:
void Init()
{
}
void Push()
{;
}
private://没有另外的访问限定符则管到结束
int*a;
int top;
}
int main()
{
Stack st1;
st1.Init();
return 0;
}
类的定义:
1.小函数,想成为inline,直接在类里面定义即可
2.如果是大函数,应该声明和定义分离。
h头文件声明 text.cpp里函数实现。小函数在头文件中的类实现。
类的作用域
class Person
{
public:
void PrintPersonInfo();
private:
char _name[20];
char _gender[3];
int _age;
};
// 这里需要指定PrintPersonInfo是属于Person这个类域
void Person::PrintPersonInfo()
{
cout << _name << " "<< _gender << " " << _age << endl;
}
声明与定义的区分
开空间就是定义,不开空间就是声明
int age; //定义 所有文件可见 如text,cpp 和 Stack.cpp调用头文件
//会有两个age 出现链接错误
extern int age; //声明 两个age一样
static int size; //定义 链接属性不一样 仅当前文件可见 使用时 static size
//两个size 不一样
class Stack
{
public:
void Init()
{
}
void Push()
{;
}
private://
int*a; //声明
int top; //声明
char _name[20];//声明
}
在调用后,创建一个结构体变量才开空间。
int main()
{
Stack.name = 100; // 编译失败:error C2059: 语法错误:“.”
Stack st1;
Stack st2; // 类的实例化
return 0
}
只有Stack类实例化出的对象st1,st2才有具体的名字.
类对象模型
存储方式:
于是 如果 创建一个 Stack A
class的空间大小
class A
{
public:
void PrintA()
{
cout<<_a<<endl;
}
void func()
{
cout<<"void A::func()"<<endl;
}
private:
char _a;
};
int main()
{
A*ptr=nullptr;
ptr->func();//这里函数正常运行
return 0;
}
由于上述的存储方式 这里的大小为1字节。 ptr为空指针程序也正常运行,因为编译时就函数已经替换,不去指针指向的对象中找函数。
// 类中仅有成员函数
class A2 {
public:
void f2() {}
};
// 类中什么都没有---空类
class A3
{};
上述大小均为1字节。空类大小为1字节,目的是为了占位,标识对象存在。
this指针
this指针是一个形参,存在于栈。
先写一个日期类
class Date
{
public:
void Init(int year, int month, int day)
{
cout<<this<<endl;
this->_year = year;
this->_month = month;
this->_day = day;
}
void Print()
{
cout <<_year<< "-" <<_month << "-"<< _day <<endl;
}
private:
int _year; // 年
int _month; // 月
int _day; // 日
int a;
};
int main()
{
Date d1, d2;
d1.Init(2022,1,11);
d2.Init(2022, 1, 12);
d1.Print();
d2.Print();
return 0;
}
Date类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,C++中针对这种情况增加一个"看不见"的指针变量(this指针),让该指针指向当前对象(函数运行时调用该函数的对象。如上.
class A
{
public:
void PrintA()
{
cout<<_a<<endl;
}
void func()
{
cout<<"void A::func()"<<endl;
}
private:
char _a;
};
int main()
{
A*ptr=nullptr;
ptr->func();//这里函数正常运行
ptr->PrintA(); //崩溃 ptr给this指针传了空指针 this解引用找_a 崩溃
return 0;
}