博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++引用(1) - 基本介绍
阅读量:4071 次
发布时间:2019-05-25

本文共 2834 字,大约阅读时间需要 9 分钟。

目录


1.基本概念

当一个变量声明为引用时,它就成为了一个名称可以改变的已存在变量了。可以使用"&"来声明一个变量为引用类型。
#include
using namespace std;int main(){ int x = 10; //ref是x的引用 int& ref = x; //x的值变成了20 ref = 20; cout << "x = " << x << endl ; //x的值现在变成了30 x = 30; cout << "ref = " << ref << endl ; return 0;}
输出:
x = 20
ref = 30
 
下面是一个使用引用来进行值交换的例子。
#include
using namespace std;void swap (int& first, int& second){ int temp = first; first = second; second = temp;}int main(){ int a = 2, b = 3; swap( a, b ); cout << a << " " << b; return 0;}
输出:
3 2
 

2.引用vs指针

引用与指针都可以用来在其它函数中修改某个函数中的局部变量。也都可以做为函数参数来传递很大的对象,或者做为函数返回值,以此避免拷贝开销,提高效率。
除去上面所述的相似点,它们之间有下面的这些不同点。
 
引用的功能没有指针那么强大:
1) 一旦引用被创建,就不能用它来再引用其它对象;引用不能被重置。而指针是可以的。
2) 引用不能为空NULL。而指针通常被赋值为NULL来显示不指向任何对象。
3) 引用在声明的时候就必须初始化。而指针并没有这种限制。
 
基于上面的限制,C++中的引用无法用来实现类似链表,树等数据结构。在Java中,引用没有上面的这些限制,可以用来实现任意的数据结构。引用在Java中功能更强大,也是Java无需支持指针的主要原因。
 
使用引用更加安全,容易:
1) 更安全: 因为引用必须被初始化,"wild引用"不可能像"wild指针"一样存在。但是,仍然可能会碰到引用所指向的是一个无效的对象(见下面的例子5和6)
2) 更容易: 引用无需使用解引用操作符来获取其值。它可以像正常变量一样来使用。'&'运算符只是在声明引用的时候需要。另外,一个对象引用中的成员可以使用点操作符'.'来访问,不像指针一样需要箭头操作符'->'来访问。
 
综上所述,只有很少的地方不能用指针,例如拷贝构造函数。在拷贝构造函数中必须使用引用来传递参数。类似地,在重载一些运算符的时候, 也必须使用引用。
 
为了更好的理解引用与指针,参考下面的这些例子。
 

2.1例子1

#include
int &fun(){ static int x = 10; return x;}int main(){ fun() = 30; std::cout << fun(); return 0;}
输出:
30
 

2.2例子2

#include
int fun(int &x){ return x;}int main(){ std::cout << fun(10); return 0;}
编译错误。
visual studio 2015提示如下:
“int fun(int &)”: 无法将参数 1 从“int”转换为“int &”。
 
修改为下面代码后,可以正常编译运行。
int x=10;
std::cout << fun(x);
输出:
10
 

2.3例子3

#include
void swap(char * &str1, char * &str2){ char *temp = str1; str1 = str2; str2 = temp;}int main(){ char *str1 = "the Los Angeles Lakers"; char *str2 = "the Chicago Bulls"; swap(str1, str2); std::cout<<"str1 is "<
<
输出:
str1 is the Chicago Bulls
str2 is the Los Angeles Lakers
 

2.4例子4

#include
int main(){ int x = 10; int *ptr = &x; int &*ptr1 = ptr;}
编译错误:
1.“ptr1”: 指向引用的指针非法
2.“初始化”: 无法从“int *”转换为“int **”
 

2.5例子5

#include
using namespace std;int main(){ int *ptr = NULL; int &ref = *ptr; cout << ref;}
编译可以通过,但是运行的时候发生了异常。引用ref访问了一个无效的地址 0x00000000.
visual studio 2015调试时抛出异常:"无法读取内存"。
 

2.6例子6

#include
using namespace std;int &fun(){ int x = 10; return x;}int main(){ fun() = 30; cout << fun(); return 0;}
输出:
10
 
将这个例子修改为下面代码:
#include 
#include
int& fun(){ int x = 10; printf("x addr: 0x%p\n", &x); return x;}int main(){ int& y = fun(); printf("y addr: 0x%p\n", &y); int* p = &y; *p = 22; printf("p addr: 0x%p\n", &p); std::cout << fun(); getchar(); return 0;}
则输出:
x addr: 0x003DFDE0  //栈地址
y addr: 0x003DFDE0
p addr: 0x003DFEC4  //栈地址
x addr: 0x003DFDE0
10  //为何是10????与编译器相关。也可能是一个随机值。

转载地址:http://ameji.baihongyu.com/

你可能感兴趣的文章
HQL语句大全(转)
查看>>
几个常用的Javascript字符串处理函数 spilt(),join(),substring()和indexof()
查看>>
javascript传参字符串 与引号的嵌套调用
查看>>
swiper插件的的使用
查看>>
layui插件的使用
查看>>
JS牛客网编译环境的使用
查看>>
9、VUE面经
查看>>
Golang 数据可视化利器 go-echarts ,实际使用
查看>>
mysql 跨机器查询,使用dblink
查看>>
mysql5.6.34 升级到mysql5.7.32
查看>>
dba 常用查询
查看>>
Oracle 异机恢复
查看>>
Oracle 12C DG 搭建(RAC-RAC/RAC-单机)
查看>>
Truncate 表之恢复
查看>>
Oracle DG failover 后恢复
查看>>
mysql 主从同步配置
查看>>
为什么很多程序员都选择跳槽?
查看>>
mongdb介绍
查看>>
mongdb在java中的应用
查看>>
Yotta企业云盘更好的为媒体广告业服务
查看>>