指针*和引用&的区别使用

时间:2022-07-23
本文章向大家介绍指针*和引用&的区别使用,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

引用&

首先,&不是地址运算符,而是类型标识符的一种,就像*也不是指针运算符一样。 本篇偏向于&运算符。

&:可以叫它引用运算符
*:可以叫它解除指针运算符

就像char *意为指向char的指针一样,int&意为指向int 的引用。

栗子来一颗:

int a;
int &at = a;
//上述声明允许将at和a互换,它们指向相同的值和内存单元,就像连体婴一样。

上面这个栗子其实很有内涵在里面 我为什么不写成下面这个形式呢?

int a;
int &at;
at = a;

在指针中是可以的,但是&不允许,&必须在声明时将其初始化。

引用经常被用作函数参数,使得函数中的变量名成为调用程序中变量的别名。这种调用方法我一直搞得晕晕的,正好这次一次性根除。这种传递参数的方法称为按引用传递。按引用传递允许被调用函数能够访问调用函数中的变量。这是C++相比C的一个超越。 来个经典的栗子:

void swap_a(int &a,int &b)
{
	int temp;
	temp = a;
	a = b;
	b = temp;
}

//顺便来个指针的
void swap_b(int *a,int *b)
{
	int temp;
	temp = *a;	//a,b是指针,*a,*b才是int
	*a = *b;
	*b = temp;
}

int main()
{
	int a = 1;
	int b = 2;
	int c = 3;
	int d = 4;
	swap_a(a,b);	//看仔细咯,这个是引用调用
	swap_b(&a,&b);	//看仔细咯,这个是指针调用
	//如果理解不了,这样理解:参数中的*和&只是走个过场,告诉人家那个参数是什么类型的
	//调用函数时的参数是a,不是*a,也不是&a
	//所以&a传的这个a是一个int类型,而*a的这个a就是指针,地址,所以要取地址传给它
	//虽然我语文不好,但是都讲到这份上了那应该是可以理解了
	return 0;
}

如果你的意图是让函数使用传给它的信息,又不想把这些信息进行改动,那么应该使用const。 将引用参数声明为const数据的好处有这些:

防止无意中被修改。
使用const参数可以兼容非const传参。

将引用用于结构

C++引入引用主要就是为了和结构和类。 它还通过让函数返回指向结构的引用而增添了一个有趣的特点,这与返回结构有所不同。

//代码太长,放段伪代码吧
struct Str
{
};

Str& test(Str &a,const Str &b)	
{
	//从b中取值,对a进行填充
	return a;//其实可以做void类型,没必要多此一举
}

int main()
{
	Str a,b,c;
	//b是有初值的,这是伪代码
	c = test(a,b);
	return 0;
}

如果test函数返回一个结构,而不是指向结构的引用,将把整个结构体复制到一个临时位置,再将这个拷贝复制给c,但是现在返回值为引用,将直接将a复制到c,效率更高。

返回引用时最重要的一点是:应避免返回函数终止时将不再存在的内存单元的引用。 下面是一个反面教材:

Str& test(const Str &d)
{
	Str &e;
	···
	return e;
}

何时使用引用参数?

程序员能够修改调用函数中的数据对象。
通过传递引用而不是整个数据对象,可以提高程序的运行速度。

指针

1、指针和const

将const用于指针有一些很微妙的地方。 可以用两种不同的方式将const关键字用于指针。

int age = 20; const int * pt = &age;
该声明指出,pt指向一个const int,因此不能使用pt来修改这个值。
现在来看一个很微妙的问题:其实age并不是一个常量,只是对于pt来说,它是一个常量。
就是说age可以改,只不过不能用pt来改而已。

注意点:不允许将常量数据赋值给非常量指针,个中理由就不用多解释了吧。
const int age = 20; int * pt = &age;

int sloth = 80; int * const finger = &sloth;
这种声明格式使得这个指针只能指向sloth,不过可以通过这个指针修改sloth的值。

2、通过指针返回字符串的函数

现在,假设需要一个返回字符串的函数,是的,函数无法返回一个字符串,但是可以返回字符串的地址,这样效率更高。

void test(char *rc)
{
	···
	memset(rc,字符串);
	···
}

相当于是使用回调函数,我个人比较喜欢这一套模式。 3、通过指针返回结构

具体操作参考第二点。 当然,这里还有另外的应用场景:

void test2(const JieGouTi1 *a,JieGouTi2 *b)
{
	//将a中的某些值赋值给b
}
//这里有一个注意点,传进去赋值的结构体指针最好用const.

4、函数指针

关于为什么要使用函数指针,我的理解还不是很深刻,毕竟功力不足。但是我知道那些回调函数都是用函数指针的,所以对函数指针必须要理解好。 这叫啥,“但行好事,莫问为啥”。

函数指针完成任务的流程是这样的:

//获取函数的地址 //声明一个函数指针 //使用函数指针来调用函数 获取函数地址

获取函数地址那是比较简单的事,如果说 void Hanshu();这是一个函数,那么它的地址就是 Hanshu。 如果函数Hanshubaba();要调用这个函数,是这样的:Hanshubaba(Hanshu); 切记不能写成:Hanshubaba(Hanshu());

声明函数指针

假设现在有这么一个函数:int test3(void *arg); //这个arg参数,回调函数里面用,要解释有点长。 现在要将之改成函数指针形式:int (*test3)(void *arg);

首先,将test3更换成(*test3),因此,(*test3)也是函数,那么test3就是函数指针。 为声明优先级,需要将 *test3 括号起来。

随机文章