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

c++引用与内联

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

c++引用与内联

关于引用方面的思维导图

注意点

1:有关引用所指向空间的问题

int main()
{
	int a = 10;
	int& b = a;//引用就是取别名,b叫做a的引用,a的别名---就是个标签
	int& c = b;
	printf("%pn", &a);//0023FC70
	printf("%pn", &b);//0023FC70,地址都是一样的
	printf("%pn", &c);//0023FC70
	int x = 1, y = 2;
	Swap(x, y);//引用就不需要取地址了
	a += 1;
	c += 1;
	printf("%dn", a);//a好像只加了1,但是确实12。
	printf("%dn", c);//c也是12哎
	return 0;
}

a,b,c使用常量10所在的空间,a+=1,c+=1,由于使用同一块空间,因此要特别注意,改变a也会改变c

2:有关引用的特性

 

int& b=10;
int e=20;
b=e;//把e的值赋值给b
//然而&b(取地址),发现地址不变,说明已经定义了的b,不能再引用其他的。

特别重要的应用---相较于c语言
typedef struct ListNode
{
	int val;
	struct ListNode* next;
}LTNode,*PLTNode;
//*PLTNode,声明了一个指向ListNode结构体的指针
void LTPushBack_C(LTNode** pphead, int x)
{
    //c语言必须要用二级指针,且外面传入必须取地址
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
}
void LTPushBack_CPP(LTNode*& phead, int x)
{
    //外面传入一个一级指针,用phead接受这个一级指针,再引用
    //而改变phead,就可以改变plist,而plist指向LTNode的空间,就可以修改其对应的值
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	if (phead == NULL)
	{
		phead = newnode;
	}
}
int main()
{

	LTNode* plist = NULL;
	//LTPushBack_C(&plist, 1);
	LTPushBack_CPP(plist, 1);

	return 0;
}

常引用

引入一个概念:读写的权限,只读相对与读写是权限的缩小,读写相对于只读是权限的放大

引用的原则是:权限只能缩小或者不变,不能放大---这是一切问题的理论依据

//引用变量,权限只能缩小或者不变,不能放大
	//const int x = 1;//这里的x是只读的
	int& y=x;//y是读写的,属于是x相对于y权限的放大
	//const int& y = x;//对y加个const去除写权力就可以了

	//int a = 2;
    //2的值复制给a,a改变并不会改变a的值
    //如果int &a=10;就不行了---因为引用a,会直接修改10,这是不被允许的。
	//const int& b = a;//缩小权限---只能读

	//const int& c = 20;//常量是一个只读的,因为你一个20不能被自己定义,不可以被修改,因此对常量取别名需要加const来修饰

那么就有

void fun(int &x)
{
}
int main()
{
    int a=10;
    fun(a);//这样就可以
    fun(10);//这样就不行了,
    return 0;
}

隐式类型转换的例子

//double d = 2.2;
//int f = d;//隐式类型转换---创建临时变量---临时变量具有常性---这样,常性就互通了.
//const int& e = d;//也就是说,临时变量是个const,到非const就是个权限的放大

前面已经说过,引用的原则是:权限只能缩小或者不变,不能放大---这是一切问题的理论依据

这里的d发生截断的时候会创建一个临时变量,而这个临时变量又是个常变量,因此在引用的时候需要加个const,防止权限进行放大

使用场景

 1:做参数

//void fun(int &x)
//{
//}

//如果像传fun(10)就必须const int &x
void fun(const int &x)
{
    传入进来的a,x作为它的别名,可以修改a的值
}
int main()
{
    int a=10;
    fun(a);//这样就可以
    fun(10);//这样就不行了,
    return 0;
}

2:做返回值

传值返回:创建临时变量,临时变量具有常性
int Count()//产生int tmp的临时变量,
{
    int n = 0;
    n++;
    // ...
    return n;
}
传引用返回
int& Count()//产生int& tmp的别名,int& ret=Count();接受
{
    int n = 0;
    n++;
    // ...
    return n;
}

但是!!!!!

传引用返回是否有点问题?

n已经被销毁了,但是你还要访问那块空间,非法访问了。---像野指针的访问

不安全样例

int& Add(int a, int b)
{
    int c = a + b;
    return c;
}
int main()
{
    int& ret = Add(1, 2);//调用完之后栈帧被销毁
    Add(3, 4);//然后,再次调用这个函数,这个函数会把原来的那块栈帧给覆盖,ret还是指向那块内存
    即,恰巧ret指向了Add(3,4)栈帧创建的位置
    cout << "Add(1, 2) is :"<< ret < 

修正

传引用返回
int& Count()//产生int& tmp的别名,int& ret=Count();接受
{
    static int n = 0;
    n++;
    // ...
    return n;
}
//这样,传引用返回,static出函数作用域就不会被销毁了。

 

总结!!!

注意:如果函数返回时,出了函数作用域,如果返回对象还未还给系统,则可以使用引用返回,如果已
经还给系统了,则必须使用传值返回。
 

指针与引用区别

内联函数---提高调用效率

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

 

//#define add(int x,int y) return ((x)+(y))//err

#define add(x,y) ((x)+(y))
int Add(int x, int y)
{
	return x + y;
}
int main()
{
	Add(10, 20);
	Add(10, 20);
	Add(10, 20);
	Add(10, 20);
	Add(10, 20);
	return 0;
}

inline在符号表里面没有地址,因此链接找不到

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

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

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