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

引用 --C++基础知识点

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

引用 --C++基础知识点

extern “c”–理解



引用–重点

1、
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
形参变量的改变要影响实参–指针或者引用

#include 
using namespace std;  // C++标准库的东西
int main()
{
	int a = 10;
	int& b = a;
	return 0;
}


2、

#include 
using namespace std;  // C++标准库的东西
int main()
{
	int a = 10;
	int& b = a;
	int& c = a;
	int& d = b;
	c = 20;
	d = 30;
	return 0;
}



3、
以前交换写法

#include 
using namespace std;  // C++标准库的东西

void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
int main()
{
    int x = 0, y = 1;
	Swap(&x, &y);
}

现在–使用引用的写法

void Swap(int& rx, int& ry)
{
	int tmp = rx;
	rx = ry;
	ry = tmp;
}
int main()
{
	int x = 0, y = 1;
	Swap(x, y);
}


栈初始化以前的写法

typedef struct Stack
{
	int* a;
	int top;
	int capacity;
}ST;
void StackInit(ST* ps)
{
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}
int main()
{
	ST st;
	StackInit(&st);
	return 0;
}

栈初始化–使用引用后的写法

typedef struct Stack
{
	int* a;
	int top;
	int capacity;
}ST;
void StackInit(ST& rs)
{
	rs.a = NULL;
	rs.top = rs.capacity = 0;
}
int main()
{
	int x = 0, y = 1;
	Swap(&x, &y);
	Swap(x, y);

	ST st;
	StackInit(st);
	
	SListNode* plist = NULL;
	SListPushBack(plist, 1);
	SListPushBack(plist, 2);
	return 0;
}


单链表对引用的使用

typedef struct SListNode
{
	struct SListNode* next;
	int val;
}SLTNode, *PSLTNode;

//void SListPushBack(PSLTNode& phead, int x)---不推荐这种写法,PSLTNode是结构图的指针
void SListPushBack(SLTNode*& phead, int x)
{
	SLTNode* newnode;
	if (phead == NULL)
	{
		phead = newnode;
	}
	else
	{
     //...
	}
}
int main()
{
	SListNode* plist = NULL;
	SListPushBack(plist, 1);
	SListPushBack(plist, 2);
	return 0;
}

4、指针变量取别名

int main()
{
	int x = 0, y = 1;
	int* p1 = &x;
	int* p2 = &y;

	int*& p3 = p1;  // 指针变量取别名
	*p3 = 10;
	 p3 = p2;
}


5、const和引用

  • 我变成你的别名的条件:不变或者缩小的你的读写权限是可以的,放大你的读写权限不行的
int main()
{
	const int a = 10;
	 int& b = a;  // 变成你的别名,还能修改你  (不行)

	int c = 20;
	const int& d = c; // 变成你的别名,不修改你  (行)
}
  • 别名可以改变,但是不是每个别名都和原名字有一样的权限(d只是别名,但不能修改)

引用转换的过程

int main()
{
	int i = 10;
	double d = i;
	const double& r = i;

	char ch = 0xff;
	int j = 0xff;
	int k = ch;
	// ch就会提升转换成int类型,再比较,提升时部位符号位
	// 这里把ch提升,你把ch变成一个int吗?,是生成一个临时变量int
	if (ch == j) 
	{
		cout << "相同" << endl;
	}
	else
	{
		cout << "不相同" << endl;
	}
	return 0;
}


6、 const的好处

typedef struct Stack
{
	int a[1000];
	int top;
	int capacity;
}ST;
void StackInit(ST& s) // 这里传引用是为了形参的改变,影响实参
{
	s.top = 0;
	s.capacity = 1000;
	// ...
}
void PrintStack(const ST& s)  
// 1、传引用是为了减少传值传参时的拷贝  
// 2、可以保护形参形参不会被改变
{
	// 假设有这样一个逻辑 -> 如果时const引用,这里就可以被检查出来
	//if (s.capacity = 0)  // 本来应该是== ,不小心写成=
	{
	}
}
void func(const int& n) // const引用做参数的第二个好处,即可接收变量,也可以接收常量
{
}
int main()
{
	ST st;
	StackInit(st);
	// ...
	PrintStack(st);
	int i = 10;
	const int j = 30;
	func(i);
	func(20);
	func(j);
	return 0;
}
  • 好处1

void PrintStack(const ST& s)
加引用 – void PrintStack(const ST& s) 本来就不需要指针,但是使用引用减少传值传参时的拷贝

加const – 可以保护形参形参不会被改变,万一写成if(s.capacity=0){}的时候会改变形参

  • 好处2
    const引用做参数的第二个好处,即可接收变量,也可以接收常量

  • 总结
    函数传参如果想减少拷贝用了引用传参,如果函数中不改变这个参数, 最好用const 引用传参

7、 引用做返回值
传值返回

int Add(int a, int b)
{
	int c = a + b;
	return c;
}
int main()
{
	 int ret = Add(1, 2);
	Add(3, 4);
	cout << "Add(1, 2) is :" << ret << endl;
	return 0;
}

传值返回

int Add(int a, int b)
{
	int c = a + b;
	return c;
}
int main()
{
	 const int& ret = Add(1, 2);//临时变量具有常性,所以需要加const才行
	Add(3, 4);
	cout << "Add(1, 2) is :" << ret << endl;
	return 0;
}


引用返回

  • 取别名返回,没有返回值,有可能带来越界访问且结果不确定因为栈帧销毁了–C的值是随机的
  • vs上没清理栈帧,结果为3
int& Add(int a, int b)
{
	int c = a + b;
	return c;
}
int main()
{
	int& ret = Add(1, 2);//ret为c的别名
	//Add(3, 4);
	printf("hello worldn");
	cout << "Add(1, 2) is :" << ret << endl;
	return 0;
}
  • 再在ret加一层引用–vs上也出错了
int& Add(int a, int b)
{
	int c = a + b;
	return c;
}

int main()
{
	int& ret = Add(1, 2);
	//Add(3, 4);
	printf("hello worldn");
	cout << "Add(1, 2) is :" << ret << endl;
	return 0;
}


总结:什么时候用引用

测试引用 – 理解
测一次测不出来

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

cpu太快了

重复一万次,一万次传字节和一万次引用

#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;
}


8、引用和指针

int main()
{
	int a = 10;
	
	int& ra = a;
	ra = 20;

	int* pa = &a;
	*pa = 30;
	return 0;
}
  • 理解性看就行

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

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

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