首先回忆一下在c语言中:函数传参有两种方式:1.传值 2.传地址
传值:在函数调用过程中会生成一份临时变量,最终把实参的值传给新分配的临时变量
优点:避免了函数调用的副作用。 缺点:无法改变实参的值
传地址:通过改变形参来改变实参的值,只能通过指针传递
引用的概念:引用不是新定义的一个变量,而是给已经存在的变量取一个别名,编译器不会为引用变量开辟内存空间
它和它引用的变量共用同一块内存空间
类型 & 引用变量名称=引用实体
void test()
{
int b=10;
int& a=b;
printf("%p\n", &a);
printf("%p\n", &b);
}
引用特性:
1.引用在定义时必须初始化
2.一个变量可以有多个引用
3.引用一旦引用一个实体,再不能引用其他实体
常引用:
void Test()
{
const int a = 10;
//int& ra = a; // 该语句编译时会出错, a 为常量
const int& ra = a;
// int& b = 10; // 该语句编译时会出错, b 为常量
const int& b = 10;
double d = 12.34;
//int& rd = d; // 该语句编译时会出错,类型不同
const int& rd = d;
}
数组可以引用:
int arr1[10];
int(& a)[10]=arr1;
引用的应用场景:1.作为函数形参:
void swap(int& left,int& right)
2.作为函数返回值 //
int& test(int& a)
注意:不能返回栈空间上的引用(因为函数被销毁空间被销毁)
错误例子:
int& Add(int a, int b) //返回了栈上空间的引用导致程序崩溃
{
int c = a + b;
return c;
}
int main()
{
int& ret = Add(10, 20);
}
传值,传地址,传引用效率比较:
传值调用时,当值被传入函数体内,临时对象生成以后,所有执行的任务都是通过直接寻址的方式执行的
而指针和大多数情况下的引用则是以间接寻址的方式执行的,所以实际的执行效率会比传值调用要低
传地址和传引用的效率一样,由下面这幅图可知
引用和指针的区别:
相同点:底层的实现方式相同,都是按照指针的方式来实现
不同点:1.引用在定义时必须初始化,指针没有要求
2.一旦一个引用被初始化为指向一个对象,就不能再指向其他对象,
而指针可以在任何时候指向任何一个同类型对象
3.没有NULL引用,但有NULL指针
4.在sizeof中的含义不同:引用结果为引用类型的大小名单指针始终
是地址*空间所占字节数个数
5.引用自加改变变量的内容,指针自加改变了指针指向
6.有多级指针,但没有多级引用
7.指针需要手动寻址,引用通过编译实现寻址
8.引用比指针使用起来相对安全
为什么要使用命名空间?
我们的代码可能和其他开发者的代码使用相同的类名、接口名、函数或常量名,如果不使用命名空间,名称会起冲突
命名空间:在C++中,变量,函数和类,这些变量,函数和类的名称将都存在于全局命名空间中会导致很多冲突,
使用命名空间的目的是将标识符的名称进行本地化,以避免命名冲突或名字污染
关键字 namespace
命名空间的定义:
// 普通的命名空间
namespace N1 // N1 为命名空间的名称
{
// 命名空间中的内容,既可以定义变量,也可以定义函数
int a;
int Add(int left, int right)
{
return left + right;
}
}
// 命名空间可以嵌套
namespace N2
{int a;
int b;
int Add(int left, int right)
{
return left + right;
}
namespace N3
{
int c;
int d;
int Sub(int left, int right)
{
return left - right;
}
}
}
// 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合
成同一个命名空间中。
namespace N1
{
int Mul(int left, int right)
{
return left * right;
}
}
// 没有名称的命名空间
namespace
{
int a;
int Div(int left, int right)
{
if(0 == right)
exit(0);
return left / right;
}
}
说明:1.一个命名空间就定义了一个作用域,命名空间中所有内容都局限于该命名空间中
2.没有名称的命名空间,它的成员只在声明该命名空间的文件中可以访问,访问时
不需要加命名空间名称,对于其他文件该命名空间中内容不可见
命名空间的使用
namespace N
{
int a = 10;
int b = 20;
int Add(int left, int right)
{
return left + right;
}
int sub(int left, int right)
{
return left - right;
}
}
using N::a;
using namespace N;
int main()
{
cout << N::b <<endl ;
cout << a << endl;
Add(10, 20);
return 0;
}