【C++】入门基础知识-2

 🍬个人主页:Yanni.—

🌈数据结构:Data Structure.​​​​​​

🎂C语言笔记:C Language Notes

🏀OJ题分享: Topic Sharing

🌼C++详解:C++ in detail

前言:

在前面介绍了一些C++的基础知识,这次延续前一个文章,今天的内容非常重要,学好之后可以为后面的类与对象打下良好的基础,加深对C++的理解。

引用

引用的概念

引用 不是新定义一个变量,而 是给已存在变量取了一个别名 ,编译器不会为引用变量开辟内存间,它和它引用的变量共用同一块内存空间。
比如: 李逵 ,在家称为 " 铁牛 " ,江湖上人称 " 黑旋风 "
类型 & 引用变量名 ( 对象名 ) = 引用实体;
void Textref()
{
	int a = 0;
	int& r = a;

	printf("%p\n", &a);
	printf("%p\n", &r);
}

下面是运行结果,可以发现地址是一模一样的,所以引用相当于给一个变量取了个名字,相当于一块空间有多个名字。

引用的特性

1.引用在定义时必须初始化。

2.一个变量可以有多个引用。(一个人可以有多个外号)

3.引用一旦引用一个实体,在不能引用其他实体。(一生只爱一个人)

void Textref()
{
	int a = 10;//初始化
	int& r = a;
	int& m = r;
	int& n = m;

	printf("%p\n", &a);
	printf("%p\n", &r);
	printf("%p\n", &m);
	printf("%p\n", &n);
}
可以发现一个变量可以有多个引用。

引用的使用场景

1.做函数参数

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

当我们要传地址调用时,C语言中使用指针来接收实参,在通过解引用进而改变实参的值,而通过引用可以直接改变实参的值,更加的简洁方便,提高了效率。

2.做返回值

int count(int a, int b)
{
	int c = a + b;
	return c;
}

int& Count(int a, int b)
{
	int c = a + b;
	return c;
}

用int做返回值的时候,函数调用栈帧,结束时会销毁栈帧,在返回值的时候会生成临时变量储存c的值,然后再通过拷贝的形式给到其他地方。

用引用做返回值时,如果是局部变量创建再栈帧中,最终这个局部变量的空间会被回收,那么返回对象就找不到了,这样可能会发生越界访问,正确的做法应该是再类型前+static,变为静态变量,这样栈帧回收空间时则不会影响到返回对象。

int& Count(int a, int b)
{
	static int c = a + b;
	return c;
}

引用与指针的区别

引用在 语法概念上 引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。
int main()
{
	int a = 10;
	int& ra = a;

	cout << "&a = " << &a << endl;
	cout << "&a = " << &ra << endl;

	return 0;
}
底层实现上 实际是有空间的,因为 引用是按照指针方式来实现 的。
int main()
{
	int a = 10;

	int& ra = a;
	ra = 20;

	int* pa = &a;
	*pa = 20;

	return 0;
}

如下图,看下引用和指针的汇编代码的对比,可以发现,两者底层的实现是相似的。

引用和指针的不同点:

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

内联函数

内联函数的概念

inline 修饰 的函数叫做内联函数, 编译时 C++ 编译器会在 调用内联函数的地方展开 ,没有函数调
用建立栈帧的开销,内联函数提升程序运行的效率。
如果在上述函数前增加 inline 关键字将其改成内联函数,在编译期间编译器会用函数体替换函数的
调用。

 内联函数的特性

1. inline 是一种 以空间换时间 的做法,如果编译器将函数当成内联函数处理,在 编译阶段,会 用函数体替换函数调用 缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率。
2. inline 对于编译器而言只是一个建议,不同编译器关于 inline 实现机制可能不同 ,一般建议:将函数规模较小 ( 即函数不是很长,具体没有准确的说法,取决于编译器内部实现 ) 是递归、且频繁调用 的函数采用 inline 修饰,否则编译器会忽略 inline 特性。
3. inline 不建议声明和定义分离,分离会导致链接错误。因为 inline 被展开,就没有函数地址 了,链接就会找不到。
int add(int x, int y)
{
	return x + y;
}
int main()
{
	for (int i = 0; i < 10000; i++)
	{
		add(1, 2);
	}
	return 0;
}

没学习内联函数之前,我们可以用宏再解决函数栈帧调用过多的问题。

#define add(x,y) return ((x)+(y))

不过宏有很多缺点:

1.不方便调试。

2.代码可读性差,可维护性差,容易误用。

3.没有类型安全的检查。

所以遇到短小且频繁调用的函数,适合用内联函数来解决,比如上面的函数要调用函数栈帧10000次,我们只要再函数前+inline,这样就可以大大增加程序的效率。

inline int add(int x, int y)
{
	return x + y;
}
int main()
{
	for (int i = 0; i < 10000; i++)
	{
		add(1, 2);
	}
	return 0;
}

auto关键字(C++11)

随着程序越来越复杂,程序中用到的类型也越来越复杂经常体现在:
1.类型难于拼写。
2.含义不明确导致容易出错。
#include <string>
#include <map>
int main()
{
 std::map<std::string, std::string> m{ { "apple", "苹果" }, { "orange", 
"橙子" }, 
   {"pear","梨"} };
 std::map<std::string, std::string>::iterator it = m.begin();
 while (it != m.end())
 {
 //....
 }
 return 0; }
在早期 C/C++ auto 的含义是:使用 auto 修饰的变量,是具有自动存储器的局部变量 ,但遗憾的
是一直没有人去使用它,大家可思考下为什么?
C++11 中,标准委员会赋予了 auto 全新的含义即: auto 不再是一个存储类型指示符,而是作为一
个新的类型指示符来指示编译器, auto 声明的变量必须由编译器在编译时期推导而得
int TestAuto()
{
return 10; }
int main()
{
int a = 10;
auto b = a;
auto c = 'a';
auto d = TestAuto();
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;
//auto e; 无法通过编译,使用auto定义变量时必须对其进行初始化
return 0; }
使用 auto 定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导 auto
的实际类型 。因此 auto 并非是一种 类型 的声明,而是一个类型声明时的 占位符 ,编译器在编
译期会将 auto 替换为变量实际的类型
总之 auto可以自动推导类型。

C++中的指针空值nullptr

void f(int)
{
 cout<<"f(int)"<<endl; 
}
void f(int*) 
{
 cout<<"f(int*)"<<endl; 
}

int main()
{
 f(0);
 f(NULL);
 f((int*)NULL);
 return 0; 
}

在C++98之后,NULL经常被当作0来处理,而非指针空值,所以在之后的学习中用nullptr在表示指针空值。

1. 在使用 nullptr 表示指针空值时,不需要包含头文件,因为 nullptr C++11 作为新关键字引入
2. C++11 中, sizeof(nullptr) sizeof((void*)0) 所占的字节数相同。
3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用 nullptr

好啦,这就是今天学习的分享啦!看到希望大家的三连呀!

如果有不当之处,欢迎大佬指正!

评论 61
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值