栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++基础篇(2)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++基础篇(2)

1、引用 1.1、引用概念

  引用是给已经存在的变量取一个别名,也就是说编译器不会给引用的变量重新开辟新的空间,引用变量和引用实体公用一块空间,采用形式为:类型& 引用变量名(对象名) = 引用实体,在代码中的形式如下:

void TestRef()
{
	 int a = 10;
	 int& ra = a;//<====定义引用类型
	 
	 printf("%pn", &a);
	 printf("%pn", &ra);
}

注意:引用类型必须和引用实体是同种类型的。

1.2、引用特性与常引用

  引用有以下特性:引用在定义时必须初始化、一个变量可以有多个引用、引用一旦引用了一个实体,就不能再引用其它实体,代码如下所示:

void TestRef()
{
	 int a = 10;
	 // int& ra; // 该条语句编译时会出错
	 int& ra = a;
	 int& rra = a;
	 printf("%p %p %pn", &a, &ra, &rra); 
}

  在常引用中还涉及如下几种情况:

void TestConstRef()
{
	 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; //引用权限的缩小,编译运行正常
}

总结:常引用可以做引用权限的平移、缩小,但不能做放大的操作。

1.3、引用使用场景

  引用可以做参数,这样形参也可改变实参案例如下:

void Swap(int& left, int& right) 
{
	 int temp = left;
	 left = right;
	 right = temp; 
}

  引用也可以做返回值,代码如下:

int& Count()
{
	 static int n = 0;
	 n++;
	 // ...
	 return n; 
}

  为什么需要用static来修饰int n?若不用static来修饰则n存放在栈区,出栈内存空间被释放,而static修饰的变量存放在静态区,静态区的变量在程序运行结束时由系统释放空间,故没问题。
总结:如果函数返回时,出了函数作用域,如果返回对象还未还给系统,则可以使用引用返回,如果已
经还给系统了,则必须使用传值返回。

1.4、传引用与传值的效率

  以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,这使得传值的效率很低,具体测试如下:

#include 
struct A
{
	 int a[10000]; 
};
void TestFunc1(A a)
{}
void TestFunc2(A& a)
{}
void TestRefAndValue()
{
	 A a;
	 // 以值作为函数参数
	 size_t begin1 = clock();
	 for (size_t i = 0; i < 10000; ++i)
	 TestFunc1(a);
	 size_t end1 = clock();
	 // 以引用作为函数参数
	 size_t begin2 = clock();
	 for (size_t i = 0; i < 10000; ++i)
	 TestFunc2(a);
	 size_t end2 = clock();
	 // 分别计算两个函数运行结束后的时间
	 cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
	 cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl; 
}


  由测试可见,两者效率相差甚远。

1.5、引用和指针的区别

  在语法角度,引用是一个别名,没有独立的空间,和引用实体公用一块空间,指针开了4or8个byte空间如下所示:

int main()
{
	 int a = 10;
	 int& ra = a;
	 
	 cout<<"&a = "<<&a<int main()
{
	 int a = 10;
	 int& ra = a;
	 ra = 20;
	 
	 int* pa = &a;
	 *pa = 20;
	 
	 return 0; 
}


引用反汇编

指针反汇编,由此可以看出两者在底层的实现是一致的。

  以下为引用和指针的不同点:
1、 引用在定义时必须初始化,指针没有要求;
2、引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体;
3、没有NULL引用,但有NULL指针;
4、在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节);
5、引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小;
6、有多级指针,但是没有多级引用;
7、访问实体方式不同,指针需要显式解引用,引用编译器自己处理;
8、 引用比指针使用起来相对更安全。

2、内联函数 2.1、内联函数的概念

  以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,如下为普通函数与内敛函数的汇编代码:

2.2、内联函数的特性

  由2.1图所知,内敛函数没有压栈的开销,是一种以空间换时间的做法,但内敛函数不适合用于码很长或者有循环/递归的函数,因为会引起编译指令的暴增,inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等等,编译器优化时会忽略内联,inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1026219.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号