c++指针和引用的详细介绍
1、指针和引用的区别
指针-对于一个类型T,T就是指向T的指针类型,也即一个T类型的变量能够保存一个T对象的地址,而类型T是可以加一些限定词的,如const、volatile等等。
引用-引用是一个对象的别名,主要用于函数参数和返回值类型,符号X&表示X类型的引用。
(1)引用不可以为空,但指针可以为空。前面也说过了引用是对象的别名,引用为空——对象都不存在,怎么可能有别名!故定义一个引用的时候,必须初始化。
(2)引用不可以改变指向,对一个对象"至死不渝";但是指针可以改变指向,而指向其它对象。说明:虽然引用不可以改变指向,但是可以改变初始化对象的内容。例如就++操作而言,对引用的操作直接反应到所指向的对象,而不是改变指向;而对指针的操作,会使指针指向下一个对象,而不是改变所指对象的内容。见下面的代码:
#include<iostream>
using namespace std;
int main(int argc,char** argv)
{
int i=10;
int& ref=i;
ref++;
cout<<"i="<<i<<endl;
cout<<"ref="<<ref<<endl;
int j=20;
ref=j;
ref++;
cout<<"i="<<i<<endl;
cout<<"ref="<<ref<<endl;
cout<<"j="<<j<<endl;
return 0;
}
对ref的++操作是直接反应到所指变量之上,对引用变量ref重新赋值"ref=j",并不会改变ref的指向,它仍然指向的是i,而不是j。理所当然,这时对ref进行++操作不会影响到j。而这些换做是指针的话,情况大不相同,请自行实验。输出结果如下:
- 引用的大小是所指向的变量的大小,因为引用只是一个别名而已;指针是指针本身的大小,4个字节。
int main()
{
string str = "123456";
string &str_ref = str;
string *str_ptr = &str;
cout<<"str.size = "<<sizeof(str)<<endl;
cout<<"str_ref.size = "<<sizeof(str_ref)<<endl;
cout<<"str_ptr = "<<sizeof(str_ptr)<<endl;
}
结果:
str.size = 24
str_ref.size = 24
str_ptr = 8
- 引用比指针更安全。由于不存在空引用,并且引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用,因此引用很安全。对于指针来说,它可以随时指向别的对象,并且可以不被初始化,或为NULL,所以不安全。const 指针虽然不能改变指向,但仍然存在空指针,并且有可能产生野指针(即多个指针指向一块内存,free掉一个指针之后,别的指针就成了野指针)。
指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名,引用不改变指向。
2、常量指针、常量引用、指针常量
2.1常量指针
常量指针:指向常量的指针,在指针定义语句的类型前加const,表示指向的对象是常量。
int i = 10;
const int* p = &i;
*p = 20; // 错误的
i = 20;
cout << i << endl; // 20
cout << (*p) << endl; // 20
常量指针定义"const int* pointer=&a"告诉编译器,* pointer是常量,不能将 * pointer作为左值进行操作。但是可以通过修改i的数值达到修改*p的数值。
2.2常量引用
常量引用:指向常量的引用,在引用定义语句的类型前加const,表示指向的对象是常量。也跟指针一样不能利用引用对指向的变量进行重新赋值操作。
int i = 10;
const int& ref = i;
ref = 20; // 错误的
i = 20;
cout << ref << endl; // 20
可以将ref理解为一个常量,无法直接修改,但是可以通过修改i的数值来修改ref的数值
2.3 指针常量
在指针定义语句的指针名前加const,表示指针本身是常量。在定义指针常量时必须初始化!而这是引用天生具来的属性,不用再引用指针定义语句的引用名前加const。
int* const p; // 错误的,必须在声明的同时被初始化
int b = 10;
int* const pointer=&b; // 正确
int c = 20;
pointer = &c; // 错误
*pointer = c;
c = 30;
cout << b << endl; // 20
cout << *pointer << endl; // 20
cout << c << endl; // 30
指针常量定义"int* const pointer=&b"告诉编译器,pointer是常量,不能作为左值进行操作,但是允许修改间接访问值,即*pointer可以修改。(pointer是一个固定的地址,不能修改,但是放在该地址上的数值可以一直被修改,pointer不能再重新指向别的数据了)
2.4 常量指针常量
int c =10;
const int *const pointer=&c;
c =20;
cout << *pointer << endl; // 20
常量指针常量:指向常量的指针常量,可以定义一个指向常量的指针常量,它必须在定义时初始化。常量指针常量定义"const int* const pointer=&c"告诉编译器,pointer和*pointer都是常量,他们都不能作为左值进行操作。
3.题目
const char * arr = "123"; // 不能修改, "123"是放在静态存储区
char * brr = "123"; // 不能修改 "123"放在静态存储区
const char crr[] = "123"; // 不能修改 (可能放在栈也可能放在静态存储区,看具体编译器)
char drr[] = "123"; // 可以修改,放在栈上