很久以前学过C++,但是后来做嵌入式一直用C,面向对象什么的都快忘光了,写一些东西权当复习C++了
一、引用
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,只能最右边连续若干参数缺省