前言
都说C++复杂,哪里复杂?(9种组合)
-
太多放对象的地方
- 堆栈
- 堆
- 全局数据区
-
太多对象的访问方式
- 变量
- 指针
- 引用
概念
- 作为本地(函数内)、全局变量,必须初始化
char c;
// r是c的别名,我们用r,就是在用c
char& r = c;
- 声明
int x = 3;
// 可以通过y修改x
int& y = x;
// 不可以通过z修改x,但x还是可以修改
const int& z = x;
异同点
-
同:与指针功能类似
-
异:绑定后不可变,但指针可变
void func(int &);
// 报错:不可以在传入参数内放表达式,要放个【地方】,放好数据的地方
func(i * 3);
- 对比
// 指针
int* f(int* x){
(*x)++;
return x;
}
// 引用
int& g(int& x){
x++;
return x;
}
int x = 0;
int& h(){
return x;
}
int main(){
int a = 0;
f(&a); //丑陋但直接
g(a); //清爽但不直接
h() = 16; //可以作为左值(指针其实也可以)
return 0;
}
- 具体哪些不同???
- 指针
- 可以是null
- 依赖已存在的对象
- 可以改变指向别的对象
- 引用
- 不可以是null
- 依赖一个已存在的变量,是该变量的【别名】
- 不可以改变到一个新的【地址】(永久的婚姻,不能再找别人)
- 指针
本质
-
实际上reference就是const指针(&可以看成*const p)
-
那为什么C++要搞这个?
- 为了让代码少点*,更加简洁美观…
一些优化细节
-
如果类的成员变量是引用,在初始化列表里就要初始化
-
return要全局变量(生命周期长)
-
传对象进入函数,为了保护对象,尽量用const reference(传入参数要是可以作左值的,i*3就不行)
// 比如传入string的object
Person(const string& name,int weight);
- 如果传入参数是const(这个是OK的)
void f(const int& i){
cout << i << endl;
}
int main(){
int i = 3;
// 传入一个匿名的变量
f(i*3);
return 0;
}
- 如果没了const(这个是错误的)
void f(int& i){
cout << i << endl;
}
int main(){
int i = 3;
// 传入一个匿名的变量
f(i*3);
return 0;
}
限制
- 没有引用之引用
- 没有引用指针
- int&* p (×)
- void f(int*& p); (√)
- 没有引用数组
关于Java
-
Java的内存模型对C++进行简化(Java就是C+±-)
-
对象都放在堆里,指针就指向堆,所以可以不用*,而且Java里不叫指针,叫引用(但与C++的引用不同)
-
Java指针的特色在哪?
- 没有*
- 不能拿来计算