#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```
自学C++ day09 引用
最新推荐文章于 2024-07-24 20:55:30 发布