不要轻视拷贝构造函数与赋值函数
由于并非所有的对象都会使用拷贝构造函数和赋值函数,程序员可能对这两个函数 有些轻视。请先记住以下的警告,在阅读正文时就会多心:
本章开头讲过,如果不主动编写拷贝构造函数和赋值函数,编译器将以“位拷贝” 的方式自动生成缺省的函数。倘若类中含有指针变量,那么这两个缺省的函数就隐 含了错误。以类 String 的两个对象 a,b 为例,假设 a.m_data 的内容为“hello”, b.m_data 的内容为“world”。 现将 a 赋给 b,缺省赋值函数的“位拷贝”意味着执行 b.m_data = a.m_data。 这将造成三个错误:一是 b.m_data 原有的内存没被释放,造成内存泄露;二是 b.m_data 和 a.m_data 指向同一块内存,a 或 b 任何一方变动都会影响另一方;三是 在对象被析构时,m_data 被释放了两次。
拷贝构造函数和赋值函数非常容易混淆,常导致错写、错用。拷贝构造函数是在对 象被创建时调用的,而赋值函数只能被已经存在了的对象调用。以下程序中,第三 个语句和第四个语句很相似,你分得清楚哪个调用了拷贝构造函数,哪个调用了赋 值函数吗?
1 #include <iostream> 2 3 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ 4 using namespace std; 5 6 //定义结构类型 7 struct student 8 { 9 int num; 10 char name[20]; 11 float grade; 12 }; 13 int main(int argc, char** argv) 14 { 15 //声明数组 16 int i,size; 17 char str[]="This is a string."; 18 int int_values[] = {51, 23, 2, 44, 45,0,11}; 19 float float_values[] = {15.1, 13.3, 22.2, 10.4, 1.5}; 20 student st_arr[]={101,"WangLin",92,102,"LiPing",85,103,"ZhaoMin",88}; 21 22 //显示char类型数组元素及其大小 23 size=sizeof(str) / sizeof(char); 24 cout<<"Number of elements in str: "; 25 cout<<size<<endl; 26 for(i=0;i<size;i++) { 27 cout<<str[i]; 28 } 29 cout<<endl; 30 31 //显示int类型数组元素及其大小 32 size=sizeof(int_values) / sizeof(int); 33 cout<<"Number of elements in int_values: "; 34 cout<<size<<endl; 35 for(i=0;i<size;i++) { 36 cout<<int_values[i]<<" "; 37 } 38 cout<<endl; 39 40 //显示float类型数组元素及其大小 41 size=sizeof(float_values) / sizeof(float); 42 cout<<"Number of elements in float_values: "; 43 cout<<size<<endl; 44 for(i=0;i<size;i++) { 45 cout<<float_values[i]<<" "; 46 } 47 cout<<endl; 48 49 //显示student类型数组元素及其大小 50 size=sizeof(st_arr) / sizeof(student); 51 cout<<"Number of elements in st_arr: "; 52 cout<<size<<endl; 53 for(i=0;i<size;i++) { 54 cout<<st_arr[i].num<<" "; 55 cout<<st_arr[i].name<<" "; 56 cout<<st_arr[i].grade<<endl; 57 } 58 return 0; 59 }