自学C++ day09 引用

#include <iostream> 
#include <time.h>
using std::cout;
using std::endl;
// 引用不会为创建的变量分配内存,它和它的引用变量公用一块内存!
// 1. 引用在定义的时候必须初始化!
// 2. 一个变量可以有多个引用!
// 3. 引用一旦引用一个实体,再不能引用其他实体!
void TestRef() {
	int a = 10;
	int& ra = a;
	int& raa = a;
	printf("%p\n", &a);
	printf("%p\n", &ra);
	printf("%p\n", &raa);
}

// 测试常引用!
void TestConstRef() {
	const int a = 10;
	// int& ra = a; 编译都不能通过!
	const int& ra = a;
	// int& b = 10;
	const int& b = 10;
	double d = 3.14;
	// int& rd = d;
	const int& rd = d;
}


// 使用场景!
// 引用做参数!
void swap(int& left, int& right) {
	int tmp = left;
	left = right;
	right = tmp;
}

// 做返回值!
int& Count() {
	static int n = 0;
	n++;
	return n;
}

// eg:
int& Add(int a, int b) {
	int c = a + b;
	return c;
}


struct A {
	int a[10000];
};

void Func1(A a){}
void Func2(A& a){}


void TestRefAndValue() {
	A a;
	// 以值作为函数参数!
	size_t begin1 = clock();
	for (size_t i = 0; i < 10000; i++) {
		Func1(a);
	}
	size_t end1 = clock();

	// 以引用作为函数参数!
	size_t begin2 = clock();
	for (size_t i = 0; i < 10000; i++) {
		Func2(a);
	}
	size_t end2 = clock();

	cout << "Func1(A) - time : " << end1 - begin1 << endl;
	cout << " Func2(A&) - time : " << end2 - begin2 << endl;
}

A a;
A Funct1() { return a; }
A& Funct2() { return a; }

void TestReturnByReference() {
	// 以值作为返回类型!
	size_t begin1 = clock();
	for (size_t i = 0; i < 10000; i++) {
		Funct1();
	}
	size_t end1 = clock();

	size_t begin2 = clock();
	for (size_t i = 0; i < 10000; i++) {
		Funct2();
	}
	size_t end2 = clock();

	cout << "TestFunct1 time : " << end1 - begin1 << endl;
	cout << "TestFunct2 time : " << end2 - begin2 << endl;
}



// 引用和指针的区别!
// 在语法概念上,引用就是个别名,没有独立空间,和其引用的实体共用同一块空间!
// 在底层实现上实际上引用是有空间的,因为引用是按照指针的方式实现的!
// 引用和指针的不同点:
//	引用在定义时必须初始化,指针没有要求!
//	引用在初始化时引用一个实体后,就不能再引用其他实体,指针可以再任何时候指向任意一个同类型的实体!
//	没有NULL引用,但有空指针!
//  在sizeof中含义不同: 引用的结果为引用类型的大小,但是指针结果始终是地址空间所占字节数!
//  引用 ++或--即引用实体++或--,指针++或-- 就是向后或向前偏移一个指向类型字节数的空间大小!
//	有多级指针,但没有多级引用!
//  访问实体方式不同,指针需要显示及引用,引用编译器自己就能处理!
//	引用比指针更安全!



// 内联函数:
// 以inline修饰的函数叫做内敛函数,编译时编译器会再调用内联函数的地方展开,没有函数压栈开销,内敛函数提升程序运行效率!

inline int AddInline(int left, int right) {
	return left + right;
}

// inline 是一种用空间换时间的做法,省去调用函数的开销.所以代码很长或者有循环/递归的函数不适宜做为内联函数!
// inline 对于编译器知识一个建议,编译器会自动优化!
// inline 不建议声明和定义分离,声明和定义必须在一个文件中,否则会发生链接错误!





// auto 关键字:
//	auto 声明的变量必须由编译器在编译时期推导而得出!
//	auto 是一个类型声明的占位符,编译器会在编译期间将auto替换为实际的变量类型!

int TestAuto() {
	return 10;
}


// auto的使用细则:
//		auto 声明指针类型变量时 auto* 和 auto 没有区别!
//		但是 auto 在声明引用类型变量时必须为` auto& 
#if 0
int main() {
	int x = 10;
	auto a = &x;
	auto* b = &x;
	auto& c = x;

	cout << typeid(a).name() << endl;
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	return 0;
}
#endif

//		使用auto在同一行声明多个变量时,这些变量必须是相同的类型!
void TestAutoOn() {
	auto a = 1, b = 2;
	// auto c = 3, d = 4.0; 
}


//		auto 不能推导的场景!
// void TestAutoTw(auto a){} // 此处编译失败,编译器无法推测a的类型!

//		auto 不能直接声明数组!
void TestAutoArr() {
	// auto a[] = { 1,2,3 };
	int b[] = { 3,4,6 };
}


// auto 范围for
// auto 范围for有条件,对于数组而言,需要提供迭代器方法begin(),end()来确定范围for的范围!
void TestAutoFor() {
	int arr[] = { 1,2,4,6,7 };
	for (auto& a : arr) {
		a *= 2;
	}

	for (auto a : arr) {
		cout << a << endl;
	}
}

#if 0
int main() {
	TestAutoFor();
}
#endif 


#if 0
// auto !
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;
	return 0;
}
#endif


// nullptr :
// 在使用nullptr表示空值时,不需要包含头文件,因为nullptr是C++11引入的关键字!
// 在 C++ 11中 sizeof(nullptr) 与 sizeof((void*)0)所占字节数相同!










#if 0
int main() {
	int& ret = Add(1, 2);
	cout << "Add (1,2) is : " << ret << endl;
	TestRefAndValue();
	TestReturnByReference();

	int rets = 0;
	rets = AddInline(1, 2);
	cout << rets << endl;
	return 0;
}
#endif```

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值