1.赋值运算符函数
String & String::operator = (String & str)
{
if(this == &str)
return *this;
delete[]m_pdata;
m_pdata = null;
m_pdata = new char[strlen(str.m_pdata)+1];
strcpy(m_pdata,str.m_pdata);
return *this;
}
1,返回值类型为该类型的引用
原因:只有返回引用,才能进行连续赋值,如果返回void,应用该赋值运算符,不能进行连续赋值
str1 = str2 = str3
2,传入的参数类型声明为常量引用
原因:如果传入的参数为实例而不是引用,从形参赋值给实参,将调用复制构造函数。参数为引用就避免这种消耗,提高效率。为了不改变传入的实例,加const。
3,释放实例自身的内存
在分配新内存之前,要释放自身已有的空间,否则将出现内存泄露。
4,自我赋值安全
判断传入的参数和当前实例(*this)是不是同一个实例。若为同一个,一旦释放了自身的内存,传入的参数的内存也要被释放。
if(this== &str)
return *this;
5,异常安全性
上面的代码,在分配内存之前释放m_pdata的内存,如果new char 出现异常,m_pdata将为成为一个空指针,这样的指针危害性很大。解决办法就是先创建一个临时实例。
char * temp = m_pdata;
m_pdata = new char (strlen(str.m_pdata) +1);
delete temp;
return *this;
异常安全性往往自动获得自我赋值安全性
2.指针和多维数组
int zippo[4][2]; 二维数组(含4个包含两个Int的数组的数组)
1.zippo :
数组名,其值是zippo首元素(两个整数值)的地址,而zippo的首元素在这里为一个包含两个int的数组。
2.zippo[0]:
包含两个int值的数组(zippo的首元素),其值也为首元素(一个整数值)地址,一个整数和含两个int的数组开始于同一个地址,所以zippo = zippo[0](值相等)。
3.zippo和zippo[0]区别:
但是,当进行指针运算时,zippo所指的对象大小是两个int,而zippo[0]所指为一个int,zippo+1 和zippo[0]+1 结果不同
4.zippo[0][0] :
首元素(一个整数值),所以zippo[0] = & zippo[0][0]。
5.*zippo,*zippo[0]
*zippo 代表首元素zippo[0]的值,zippo[0]值为&zippo[0][0]。所以*zippo = &zippo[0][0] ,两边同时再取地址,**zippo = zippo[0][0]。zippo为地址的地址。
*zippo[0]代表zippo[0][0]的值。
6.分析* ( *(zippo+2)+1)
zippo+2 :第三个(包含两个int的数组)的地址。
*(zippo+2):第三个(包含两个int的数组),实际为第三排第一个元素的地址。
*(zippo+2)+1:第三个包含两个int的数组的第二个元素地址。
* (*(zippo+2)+1):数组第三行第二个元素的值(zippo[2][1])
7.指向多维数组的指针
这个最近也是吃过一次亏,好久没用了,突然用的时候,声明指向二维数组的指针,直接来了一个int** ptr,还自我感觉良好,调试的时候就傻逼了,这个确实是个容易犯错的地方。
声明指向zippo的指针变量ptr。上面第一条已经说过,zippo是首元素(两个int)的地址。所以ptr也要指向含两个int的数组。
int(*ptr)[2] //ptr指向含两个int的数组的指针。
顺便我们再解释下:
int *ptr[2],因为[]的优先级比较高,所以ptr就成了包含两个指向int的指针的数组。
在声明以二维数组为参数的函数时
void function(int (*ptr)[2]);
void function(int ptr[][2]); //第一个空的方括号表明ptr是一个指针
8.指针之间的赋值规则
要类型相同,无类型强制转换
int * pt;
int (* pa)[3];
int ar1[2][3];
int ar2[3][2];
int **p2; //指向指针的指针
pt = &ar1[0][0] ; //都指向int
pt = ar1[0] ; //都指向int
pt = ar1; //ar1指向3个int值构成的数组,pt指向int
pa = ar1 ; //都指向int[3]
p2 = ar2; //p2指向int的指针,ar2指向2个int构成的数组
*p2 = ar2[0] ; //都是指向int
p2 = * pt; //都是指向int*
int * p1;
const int * p2;
const int ** pp2;
p1 = p2 ; //非法,不能把const指针赋给非const
p2 = p1; //合法
pp2 = & p1; //非法,非const 赋给const,只能进行一层间接运算
在进行两层间接运算时,赋值不再安全
const int **pp2;
int * p1;
const int n = 13;
pp2 = & p1;
*pp2 = &n;
*p1 = 10; //将改变const n 的值。