对指针和引用的理解(c++)
1.指针
typedef说明一种新类型名,来代替已有类型名。
a.案例:typedef char* String_t和#define String_d char *这两句在使用上的区别?
1)前者声明一个类型的别名,在编译时处理,有类型检查。后者是一个简单的替换,在预编译时处理,无类型检查。
2)String_t a,b;中a和b都是char*类型的。但是String_d a,b;中a是char*类型的,b是char类型的。
b.对 typedef string *pstring;
const pstring cstr;的理解。
cstr是一种指针,指向string类型的const对象。但这是错误的。错误的原因在于将typede当作宏替换似的文本扩展了。声明 const pstring时,const修饰的是pstring的类型。
这是一个指针。所以该声明应该是把cstr定义为指向string类型对象的const指针。等价于:string * const cstr;
c.void*指针。void* 指针表明该指针与一地址值相关,但是不清楚存储在该地址值上的对象类型。void*指针只支持有限的操作:
1)与另外一个指针进行比较
2)向函数传递void*指针或从函数返回void*指针。
3)给另外一个void*指针赋值。不允许使用void*指针操作他所指向的对象。当函数返回void*类型时,表示返回一个特殊指针类型。而不是返回类型为void那样表示无返回值。
d.用typedef简化函数指针的定义
typedef bool (*cmpFcn)(const string &,const string &);
该定义表示cmpFcn是一种指向函数的指针类型的名字。该指针类型为指向返回bool类型并带两个const string 引用形参的函数的指针,在要使用这种函数指针类型时,
只需直接使用cmpFcn即可,不必每次都把整个类型声明全部写出来。
在引用函数名但又没有调用该函数时,函数名将被自动解释为指向函数的指针。
bool lengthCompare(const string &,const string &);
直接引用函数名等效于在该函数名上应用取地址操作符:
cmpFcn pf1=lengthCompare;
cmpFcn pf2=&lengthCompare;
函数指针的使用
指向函数的指针可以用于调用他所指向的函数。可以不需要使用解引用操作符,直接通过指针调用函数。
例如: typedef bool(*cmpFcn)(const string &,const string &);
bool lengthCompare(const string &,const string &);
则:cmpFcn pf=lengthCompare;
lengthCompare("hi","bye"); //直接调用lengthCompare函数
pf("hi","bye"); // 利用函数指针调用lengthCompare函数,未使用*
(*pf)("hi","bye"); // 利用函数指针调用lengthCompare函数,使用*
函数的形参为指针和返回指向函数的指针
允许将形参定义为函数类型,但是函数的返回类型则必须是指向函数的指针,而不能是函数。具有函数类型的形参所对应的实参将被自动转换为指向相应函数类型的指针。
但是,当返回的是函数类型时,同样的转换操作将无法实现。
func f2(int); //错误,func无法自动转换。
func* f3(int); //正确,f3返回一个函数指针
2.引用
引用就是对象的另外一个名字。c++中规定一旦定义了引用,就必须把它跟一个变量绑定起来,并且不能修改这个绑定。
不能定义引用类型的引用,但是可以定义其他类型的引用。
使用引用和指针都可以间接的访问另外一个值,但是他们之间有几个重要的区别。
1)引用不能为空,当引用被创建时,他必须被初始化,而指针可以为空值,可以在任何时候被初始化。
2)一旦一个引用被初始化为指向一个对象,他就不能改变为对另外一个对象的引用,指针则可以在任何时候指向另外一个对象。
3)不可能有NULL引用。必须确保引用和一块合法的存储单元关联。
4)sizeof(引用)得到的是所指向变量(对象)的大小,而sizeof(指针)得到指针本身的大小。
5)给引用赋值修改的是该引用所关联的对象的值,而并不是使引用于另外一个对象的关联。
6)引用使用时不需要解引用,而指针需要解引用,引用和指针的自增(++)操作符运算意义不同。
7)如果返回动态分配的对象或内存,必须使用指针,引用可能引起内存泄漏。
8)当使用&运算符取一个引用的地址时,其值为所引用变量的地址。而对指针使用&运算,取得是指针变量的地址。
可见引用本质只是一个对象的别名。对引用别名的操作即是对本身变量的操作。
const引用
const引用是指向const对象的引用。当引用的对象是const对象时,引用也必须是const。
const int ival=1024;
const int &refVal=ival; //正确
int& ref2=ival; //错误
如果既要既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应该使用常引用。常引用主要用于定义一个普通变量只读属性的别名。
作为函数的传入形参,避免实参在调用函数中被意外改变。
引用做类的数据成员
引用类型数据成员的初始化有一下几个特点:
1)不能直接在构造函数中初始化,必须用到初始化列表。
2)凡是用引用类型的数据成员的类,必须定义构造函数。
案例:
class ConstRef{
public:
ConstRef(int ii):i(ii),ci(i),ri(ii){} //ci与ri必须在成员初始化列表中初始化,因此必须自定义构造函数,书写成员初始化列表
private:
int i;
const int ci;
int &ri;
};