More Effective C++ 第一讲,指针和引用

1. 指针和引用的区别

  • 相同点:指针和引用都是让你间接引用其它对象。
  • 不同点:
  • 1.引用:声明时必须初始化,并且以后不能改变(即不能给引用重新赋值),但是指定的对象其内容可以改变。
    指针:声明可以不初始化,并且可以被重新赋值以指向另一个不同的对象
  • 2.从内存分配上看,程序为指针变量分配内存区域,而不为引用分配内存区域。
  • 3.不存在指向空值的引用这个事实。
  • 4.引用比指针更安全。由于不存在空引用,并且引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用,因此引用很安全。对于指针来说,它可以随时指向别的对象,并且可以不被初始化,或为NULL,所以不安全。
  • 5.引用的大小是所指向的变量的大小,因为引用只是一个别名而已;指针是指针(地址)本身的大小,32位系统下,一般为4个字节。
	//指针与引用的另一个重要的不同是指针可以被重新赋值以指向另一个不同的对象。
	//但是引用则总是指向在初始化时被指定的对象,以后不能改变。
    std::string s1("Nancy");
	std::string s2("Clancy");
	std::string& rs = s1; // rs引用s1
	std::string* ps = &s1; // ps指向s1
	rs = s2; // rs仍旧引用s1,但是s1的值现在是"Clancy"

1.1 常量指针和指针常量

1.1.1 常量指针

解释:const int *PtrConst 或者是 int const PtrConst (即const 在的左边)
常量指针就是指向常量的指针,但是这里指的“常量”是在解引用时起到所谓常量的作用,并非是指向的变量就是常量,指向的变量既可以是非常量也可以是常量。总体意思是不能修改指向某变量的值。
功能:让指针指向一个常量,可以防止使用指针来修改所指向的值。

注意点:
1.常量指针指向的对象不能通过这个指针来修改,可是仍然可以通过原来的声明修改;

	int a = 1;
	const int *p = &a;
	cout << *p << a << std::endl;  //此时这两个值应该是相等的  *p=a=1
	a = 2;//可以,可以通过原来的声明来修改
	*p = 3; //报错,不可以,不能通过指针来修改指向的对象
	cout<< *p << a << std::endl;//  *p=a=2

因为不能通过这个指针来修改,所以可以用常量指针当函数的参数使用。
2. 常量指针还可以指向别处,因为指针本身只是个变量,只不过指向的对象是所谓的"常量",可以指向任意地址;

	int a = 1;
	const int *p = &a;  //指针指向a
	cout << "p= "<< *p <<";" << "a=" << a << std::endl;  // p=a=1
	int b = 2;
	p = &b;  //指针指向b
	cout<<"p= "<<  *p << ";" <<"b=" <<  b<< std::endl;  //p=b=2

3.可以将const 变量的地址赋给指向const 的指针(即常量指针)。但是不可以将const 的地址赋给常规指针,除非使用强制类型转换,const_cast

	const  int  a = 1;   //const修饰的变量
	const int * p = &a;	//可以
	
	const  int  a = 1;   //const修饰的变量
	int * p = &a;	//常规指针,不可以
	
	const int a = 1;
	int *p = const_cast<int*>(&a) //可以

1.1.2 指针常量

int const *PtrConst;
本质是一个常量,而用指针修饰它。指针常量的值是指针。
1.必须初始化,只能指向一个变量,绝不可再改变指向另一个变量

    int *const ConstPtr;//报错,error C2734: “ConstPtr”: 如果不是外部的,则必须初始化常量对象
    int a=1;    
    int *const ConstPtr=&a;     //可以,目前是只指向这一个变量
    int b = 2;   
    ConstPtr=&b;   				//不可以,不可以在改变指针的指向了!只能指向另一个变量

2.指向的地址所对应的内容可以变化

	int a=1;    
	int *const ConstPtr=&a;    
	ConstPtr = 3; //可以

如果出现在星号两边,表示被指物和指针都是常量。

1.2 常量引用用法

常量引用”其实是**“对 const 的引用”**的简称。因此不可以通过该引用来修改它所指向的对象的值。

  1. 指向常量对象时,一定要使用“常量引用”,而不能是一般的引用。
const int ci = 1024;
const int &r1 = ci;         // 正确:引用及其对应的对象都是常量
int &r2 = ci;               // 错误:试图让一个非常量引用指向一个常量对象
  1. 指向非常量对象时,也可以用“常量引用”,但不允许用该引用修改非常量对象的值。
    “常量引用”仅对引用可参与的操作做出了限定,对于引用的对象本身是不是一个常量未作限定。
    因为对象也可能是个非常量,所以允许通过其他途径改变它的值:
int i = 42;
int & r1 = i;                // 普通引用指向非常量对象 i
const int & r2 = i;          // 常量引用也绑定非常量对象 i
r1 = 40;                     // 正确,r1并非常量引用 r1 = i = 42
r2 = 0;                      // 错误,r2是一个常量引用 
  1. 引用的类型必须和所引用的类型严格匹配,且不能与字面值或者某个表达式的计算结果绑定在一起,
    但是 “常量引用” 是例外(只要被引用的类型能够转换为常量引用的类型)。
int i = 42;
const int &r1 = i;          // 正确:指向非常量对象
const int &r2 = 42;         // 正确:r2 是一个常量引用
const int &r3 = r1 * 2;     // 正确:r3 是一个常量引用
int &r4 = r1 * 2;           // 错误:r4 是一个普通的非常量引用
	int i = 40;
	int &r1 = i;  				// 普通引用r1 指向 i 
	const int &r3 = i * 2;		// 常量引用r3 指向 2i
	cout << "r3 = " << r3 << std::endl;  // r3 = 80
	
	r1 = 30;  //普通引用改变了 i 的值, i = 30
	cout << "r3 = " << r3 << "    i = " << i << std::endl;//测试r3是否改变. 依然没变 r3=80

在这些情况下,“常量引用”实际上是绑定了一个临时量(temporary)对象。也就是说,允许“常量引用”指向一个临时量对象。
4. 在函数参数中,使用常量引用非常重要。因为函数有可能接受临时对象,而且同时需要禁止对所引用对象的一切修改。
5. 去掉常量的办法是调用const_cast函数

你可能感兴趣的:(more,efficive,c++,c++,visual,studio,开发语言,数据结构)