很久以前学过C++,但是后来做嵌入式一直用C,面向对象什么的都快忘光了,写一些东西权当复习C++了


文章目录

  • ​​一、引用​​
  • ​​1、普通引用​​
  • ​​2、常引用​​
  • ​​二、再看const​​
  • ​​三、动态内存分配​​
  • ​​四、内联函数、重载函数、函数缺省值​​
  • ​​1、内联函数​​
  • ​​2、重载函数​​
  • ​​3、函数缺省值​​

一、引用

1、普通引用

  • 简介
    (1)设置一个变量的引用,相当于给这个变量起一个别名,变量的引用等价于这个变量(修改一个,另一个也变化)
    (2)​​​变量类型 & 引用名 = 变量名​
int n=4;
int &r=n; //r引用了n,r类型为int &
  • 注意
    (1)定义引用后一定要将其初始化为引用某个变量(定义时必须同时初始化
    (2)初始化后,它就一直引用该变量,不会再引用其他变量了
    (3)引用只能引用变量,不能引用常量和表达式
  • 特点
    (1)引用具有传递性:int & r1=a; int &r2=r1; 则r1,r2都引用a(可以用引用初始化引用
    (2)引用可以作为函数参数
    (3)引用可以作为函数返回值,从而可以把函数调用放在赋值号左边,对被引用变量赋值(一般不这样做)
#include<iostream>
using namespace std;

//c++风格的交换,引用作为函数参数
void swap_in_cpp(int &a,int &b)
{
int t;
t=a,a=b,b=t;
}

//此函数返回全局变量N的引用
int N=0;
int &getN()
{
return N;
}

int main()
{
getN()=10; //这相当于给N的引用赋值,会修改N
cout<<10;
}

2、常引用

  • 简介
    (1)常引用是一种特殊的引用,和普通引用相比,不能通过常引用修改被引用变量的值
    (2)​​​const 变量类型 & 引用名 = 变量名​
int n=4;
const int &r=n; //r是n的常引用,对r赋值会报错
  • 注意
    (1)不能通过常引用修改被引用的内容(会报错),但被引内容不一定不可改变
    (2)不能用常量和常引用初始化普通引用,反之可以。例如:​​int &​​类型的引用和​​int​​类型的变量可以用来初始化​​const int &​​类型的引用;​​const int​​类型的常变量和​​const int &​​型的引用不能用来初始化 ​​int &​​类型的引用(除非强转类型)。这是由于我们倾向于认为有常引用的变量是不应被修改的,如果可以可以用常引用初始化普通引用,那么就能通过普通引用修改变量值,这是不好的
    (3)​​const int &​​和​​int &​​是不同的类型
  • 常见用法
    (1)通常在函数参数中使用常引用,从而避免参数在函数内被意外修改
int add(const int &a,const int &b)
{
//a++; //报错
return a+b;
}

二、再看const

​const​​不是C++的新保留符,以前用得少,所以这里也一起总结一下

  • 定义常量
    (1)代替#define,可以进行类型检查
  • 定义常指针
    (1)​​​const 变量类型 * 指针名 = &变量名​​ (2)不可以通过常量指针修改所指的内容(会报错)
    (3)不能把常量指针赋值给非常量指针,反之可以,原因同上面提到的常引用
    (4)通常在函数参数中使用常指针,从而避免参数在函数内被意外修改
//不可以通过常量指针修改所指的内容
{
int n,m;
const int *p=&n;
//*p=5; //编译出错
n=4; //可以直接修改被指向的变量
P=&m; //可以修改常量指针的指向
}

//不能把常量指针赋值给非常量指针,反之可以
{
const int *p1;
int *p2;
p1=p2; //ok
//p2=p1; //编译错误
p2=(int *)p1; //ok
}

//避免参数在函数内被意外修改
Void myprintf(const char * p)
{
Strcpy(p,"this"); //修改了p内容,编译出错(Strcpy第一个参数为char型,不可以用const char 赋值)
Printf("%s", p); //ok
}
  • 定义常引用
    (1)同上

三、动态内存分配

  • 分配一个变量:
    (1)​​类型名 *变量名 = new 类型名​​( 例:int *p = new int; )
    (2)这句动态分配出一块大小为​​sizeof(类型)​​的空间,并将起始地址赋值给P
  • 分配一个数组:
    (1)​​类型名 *变量名 = new 类型名[数组长度N]​​,( 例:int *p = new int[10]; )
    (2)这句动态分配出一块大小为​​N*sizeof(类型)​​的空间,并将起始地址赋值给P
  • 释放动态分配的变量:
    (1)​​delete 指针名​​,( 例:delete p;)
    (2)被delete的指针必须指向new出来的指针,否则编译没问题,运行可能出错
    (3)一片空间不能被delete多次
  • 释放动态分配的数组:
    (1)​​delete [] 指针名​​,( 例:int *p=new int[20]; )
    (2)被delete的指针必须指向new出来的数组
    (3)一片空间不能被delete多次
#include<iostream>
using namespace std;

int main()
{
int *p=new int[5];
float *q=new float;

for(int i=0;i<5;i++)
p[i]=i,cout<<p[i]<<" ";

*q=1.234;
cout<<*q<<endl;

delete []p;
delete q;
return 0;
}

四、内联函数、重载函数、函数缺省值

1、内联函数

  • 函数调用有时间开销,为了减少开销,引入内联函数机制。编译器处理内联函数调用语句时,直接把函数代码嵌入调用处,从而不会产生调用指令
  • 定义:在函数定义前加​​inline​​关键字
  • 注意:不一定加了​​inline​​就一定按内联函数处理,具体要靠编译器判断
  • 示例:
//像这种函数没多少行,但是频繁调用的,适合用内联
inline int Max(int a,int b)
{
if(a>b) return a;
return b;
}

2、重载函数

  • 一个或多个函数,名字相同,然而参数个数参数类型不同,这叫做函数的重载
  • 注意避免调用时出现二义性问题
int Max(double f1,double f2){}
int Max(int n1,int n2){}
int Max(int n1,int n2,int n3){}

Max(3.4, 2.5) //调用1
Max(2,4) //调用2
Max(1,2,3) //调用3
Max(3, 2.4) //error 二义性

3、函数缺省值

  • C++中函数可以让最右边的连续若干个参数设置缺省值,调用时对应位置不写参数就是使用缺省值
  • 参数缺省值只能出现在函数的声明中,而不能出现在定义体中。
  • 参数可缺省的目的在于提高程序的可扩充性
    如果某个写好的函数要添加新参数,而原先那些调用此函数的语句未必要使用这些新参数,可以使用缺省参数,从而避免修改以前的调用语句
func(int x1,int x2=2,int x3=3){}

func(10); //func(10,2,3);
func(10,8); //func(10,8,3);
func(10, ,8); //error,只能最右边连续若干参数缺省