1. 指针和引用的区别
- 相同点:指针和引用都是让你间接引用其它对象。
- 不同点:
- 1.引用:声明时必须初始化,并且以后不能改变(即不能给引用重新赋值),但是指定的对象其内容可以改变。
指针:声明可以不初始化,并且可以被重新赋值以指向另一个不同的对象 - 2.从内存分配上看,程序为指针变量分配内存区域,而不为引用分配内存区域。
- 3.不存在指向空值的引用这个事实。
- 4.引用比指针更安全。由于不存在空引用,并且引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用,因此引用很安全。对于指针来说,它可以随时指向别的对象,并且可以不被初始化,或为NULL,所以不安全。
- 5.引用的大小是所指向的变量的大小,因为引用只是一个别名而已;指针是指针(地址)本身的大小,32位系统下,一般为4个字节。
std::string s1("Nancy");std::string s2("Clancy");std::string& rs = s1; std::string* ps = &s1; rs = s2;
1.1 常量指针和指针常量
1.1.1 常量指针
解释:const int *PtrConst 或者是 int const PtrConst (即const 在的左边)
常量指针就是指向常量的指针,但是这里指的“常量”是在解引用时起到所谓常量的作用,并非是指向的变量就是常量,指向的变量既可以是非常量也可以是常量。总体意思是不能修改指向某变量的值。
功能:让指针指向一个常量,可以防止使用指针来修改所指向的值。
注意点:
1.常量指针指向的对象不能通过这个指针来修改,可是仍然可以通过原来的声明修改;
int a &#61; 1;const int *p &#61; &a;cout << *p << a << std::endl; a &#61; 2;*p &#61; 3; cout<< *p << a << std::endl;
因为不能通过这个指针来修改&#xff0c;所以可以用常量指针当函数的参数使用。
2. 常量指针还可以指向别处&#xff0c;因为指针本身只是个变量&#xff0c;只不过指向的对象是所谓的"常量"&#xff0c;可以指向任意地址&#xff1b;
int a &#61; 1;const int *p &#61; &a; cout << "p&#61; "<< *p <<";" << "a&#61;" << a << std::endl; int b &#61; 2;p &#61; &b; cout<<"p&#61; "<< *p << ";" <<"b&#61;" << b<< std::endl;
3.可以将const 变量的地址赋给指向const 的指针&#xff08;即常量指针)。但是不可以将const 的地址赋给常规指针&#xff0c;除非使用强制类型转换&#xff0c;const_cast
const int a &#61; 1; const int * p &#61; &a; const int a &#61; 1; int * p &#61; &a; const int a &#61; 1;int *p &#61; const_cast<int*>(&a)
1.1.2 指针常量
int const *PtrConst;
本质是一个常量&#xff0c;而用指针修饰它。指针常量的值是指针。
1.必须初始化&#xff0c;只能指向一个变量&#xff0c;绝不可再改变指向另一个变量
int *const ConstPtr;int a&#61;1; int *const ConstPtr&#61;&a; int b &#61; 2; ConstPtr&#61;&b;
2.指向的地址所对应的内容可以变化
int a&#61;1; int *const ConstPtr&#61;&a; ConstPtr &#61; 3;
如果出现在星号两边&#xff0c;表示被指物和指针都是常量。
1.2 常量引用用法
常量引用”其实是**“对 const 的引用”**的简称。因此不可以通过该引用来修改它所指向的对象的值。
- 指向常量对象时&#xff0c;一定要使用“常量引用”&#xff0c;而不能是一般的引用。
const int ci &#61; 1024;
const int &r1 &#61; ci;
int &r2 &#61; ci;
- 指向非常量对象时&#xff0c;也可以用“常量引用”&#xff0c;但不允许用该引用修改非常量对象的值。
“常量引用”仅对引用可参与的操作做出了限定&#xff0c;对于引用的对象本身是不是一个常量未作限定。
因为对象也可能是个非常量&#xff0c;所以允许通过其他途径改变它的值&#xff1a;
int i &#61; 42;
int & r1 &#61; i;
const int & r2 &#61; i;
r1 &#61; 40;
r2 &#61; 0;
- 引用的类型必须和所引用的类型严格匹配&#xff0c;且不能与字面值或者某个表达式的计算结果绑定在一起&#xff0c;
但是 “常量引用” 是例外&#xff08;只要被引用的类型能够转换为常量引用的类型&#xff09;。
int i &#61; 42;
const int &r1 &#61; i;
const int &r2 &#61; 42;
const int &r3 &#61; r1 * 2;
int &r4 &#61; r1 * 2;
int i &#61; 40;int &r1 &#61; i; const int &r3 &#61; i * 2; cout << "r3 &#61; " << r3 << std::endl; r1 &#61; 30; cout << "r3 &#61; " << r3 << " i &#61; " << i << std::endl;
在这些情况下&#xff0c;“常量引用”实际上是绑定了一个临时量&#xff08;temporary&#xff09;对象。也就是说&#xff0c;允许“常量引用”指向一个临时量对象。
4. 在函数参数中&#xff0c;使用常量引用非常重要。因为函数有可能接受临时对象&#xff0c;而且同时需要禁止对所引用对象的一切修改。
5. 去掉常量的办法是调用const_cast函数