1 什么是引用
在c++中,引用可以理解为“一个已经存在变量的别名”。它不是创建一个新的变量,而是给原变量再起一个名字。
引用的基本语法是:数据类型& 引用名 = 引用对象;


① 引用是变量的别名,引用在定义时必须初始化。
② 引用和原变量操作的是同一个对象。
③ 引用和原对象的地址相同。
④ 多个引用可以引用同一个对象。引用一旦绑定,不能改绑。
2 引用的使用
引用在实践中主要是引用传参和引用做返回值中减少拷贝提高效率和改变引用对象的同时改变被引用对象。
① 引用作为函数形参,修改形参影响实参。


#include<iostream>
#include<cassert>
using namespace std;
typedef struct seqlist
{
int a[10];
int size;
}seqlist;
typedef struct listnode
{
int val;
struct listnode* next;
}lnode, *linklist;
//typedef struct listnode lnode;
//typedef struct listnode* linklist;
void seqlistinit(seqlist& s)
{
s.size = 0;
}
void seqlistpush(seqlist& s, int x)
{
s.a[s.size++] = x;
}
//void linklistpushback(lnode** l, int x)
//void linklistpushback(lnode*& l,int x)
void linklistpushback(linklist& l, int x)
{
linklist newnode = (linklist)malloc(sizeof(lnode));
assert(newnode);
//...
newnode->val = x;
newnode->next = null;
if (l == null)
{
l = newnode;
}
else
{
linklist ptr = l;
while (ptr->next) {
ptr = ptr->next;
}
ptr->next = newnode;
}
}
int main()
{
seqlist s;
seqlistinit(s);
seqlistpush(s, 1);
seqlistpush(s, 2);
seqlistpush(s, 3);
seqlistpush(s, 4);
//lnode* l = null;
linklist l = null;
linklistpushback(l, 1);
linklistpushback(l, 2);
linklistpushback(l, 3);
return 0;
}② 引用传递大型对象可以避免值拷贝。不需要复制整个结构体或类对象,因此更加高效。


③ 引用可以引用指针。表示“指针变量的引用”,能够直接修改外部指针变量所保存的地址。


④ 引用作为返回值可修改返回对象,减少拷贝,提高效率。
#include<iostream>
#include<cassert>
using namespace std;
typedef struct seqlist
{
int* a;
int size;
int capacity;
}seqlist;
void seqlistinit(seqlist& s, int n = 4)
{
s.a = (int*)malloc(sizeof(int) * n);
s.size = 0;
s.capacity = 4;
}
void seqlistpushback(seqlist& s, int x)
{
s.a[s.size++] = x;
}
int& seqlistat(seqlist& s, int i)
{
assert(i < s.size);
return s.a[i];
}
int main()
{
seqlist s;
seqlistinit(s);
seqlistpushback(s, 1);
seqlistpushback(s, 2);
seqlistpushback(s, 3);
seqlistpushback(s, 4);
for (int i = 0;i < s.size;i++)
{
seqlistat(s, i) += 1;
}
for (int i = 0;i < s.size;i++)
{
cout << seqlistat(s, i) << endl;
}
return 0;
}
⑤ 函数可以返回引用,但返回的引用所绑定的对象,在函数结束后必须仍然存在。
#include<iostream>
#include<cassert>
using namespace std;
int& func1()
{
int x = 10;
return x;
}
int& func2()
{
int y = 1000;
return y;
}
int main()
{
int x = func1();
cout << x << endl;
int& y = func1();
cout << y << endl;
func2();
//悬空引用y可能还保存着对这块位置的使用
cout << y << endl;
return 0;
}

3 const与引用、指针之间的绑定和类型转换规则
可以把“普通对象”交给只读引用/只读指针使用,但不能把“const对象”交给可修改引用,也不能通过类型转换随意去掉const属性。
const转换原则:可以加const,不能随便去const;可以从“可读可写”变成“只读”,不能反过来。

const与引用、指针结合时的基本规则:普通对象既可以通过普通引用或普通指针方式,也可以通过const引用或指向const的指针进行只读访问;而const对象不能绑定到非const引用,指向const的指针也不能隐式转换成普通指针。
const引用具有比普通变量更宽松的绑定规则。
const引用既可以绑定左值,也可以绑定临时对象;当表达式的结果不是一个可以直接绑定的同类型对象时,编译器可能先构造一个临时对象,再让const去引用它。
const t&经常作为函数参数使用,它既能避免不必要的对象拷贝,又能防止通过改引用修改对象,同时能够接受普通对象、const对象和临时对象。

① 左值是可是取地址、有明确内存位置、生命周期持续到作用域结束的表达式。左值表示一个有名字、有固定存储位置、可以被持续访问的对象。
② 右值通常是临时对象,没有持久地址。
③ c++之父bjarne的说法:左值是有身份的表达式。左值强调的是“对象有身份”。
④ c++语言规定:非const左值引用t&主要用于绑定左值,不允许直接绑定普通右值/临时值。
4 引用与指针的关系
指针是“存地址的变量”,引用是“已有对象的别名”。两者都能间接操作对象,但表达的语义不同:指针强调“指向谁”,引用强调“我就是它的另一个名字”。
① 指针可以为空,也可以改变指向;引用必须初始化并且绑定后不能改绑。
② 指针访问对象通常需要解引用,并支持指针运算和多级指针,而引用使用和普通变量类似。
③ sizeof含义不同。指针始终是地址空间所占字节个数,引用结果为引用类型的大小。
到此这篇关于c++中的引用与指针详解的文章就介绍到这了,更多相关c++引用与指针内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论