class的三大函数是:
1.拷贝构造。
2.拷贝赋值。
3.析构。
其他备忘:
1. 构造函数函数分两类:拷贝构造和默认构造。
2. strlen计算长度时,不包含末尾的 '\0'。
例如如下字符串类String的拷贝构造函数:
String::String(const String& str) { m_data = new char[strlen(str.m_data) + 1]; strcpy(m_data,str.m_data); }
此处若不做 strlen(...) + 1,会造成新的m_data字符串没有结束符的问题。(而且貌似strcpy也会出错。)
3. 构造函数放在private里面时,对象将不能直接构造。
4. 对于有指针成员的类,注意要自己实现三大函数。使用默认生成的函数会造成不良后果:
(1)使用默认的拷贝构造和拷贝赋值,会造成新生成的对象内部指针指向来源对象的动态分配空间,造成动态分配空间的共享。这会造成不可预计的严重错误。(比如1,其中一个对象更改了“动态空间”,另一个对象的所谓的“动态空间”也被一起改动了。比如2,其中的一个对象销毁了空间释放了,此时一个对象的“动态空间”,可能又会分配给其他对象,读出的数据可能被其他对象更改,或者自己写入数据又更改了其他对象的数据。等等)
(2)使用默认的析构函数,则会造成动态生成的空间没有被释放,造成内存泄漏的问题。
5. 拷贝复制函数注意添加入口判断。
例如字符串类String的拷贝复制函数:
String& String::operator= (const String& str) { if(this == &str) { return *this; } delete[] m_data; m_data = new char[strlen(str.m_data) + 1]; strcpy(m_data,str.m_data); return *this; }
此处若不做错误处理,会因为后面的delelte[] m_data;操作而把自己的数据删除,造成数据丢失,以及后面strlen、strcpy执行出错的问题。
6. 拷贝复制函数编写时要考虑 s3 = s2 = s1这种连续拷贝复制的情况。
例如字符串类String的拷贝复制函数:
String& String::operator= (const String& str) { ...... return *this; }
此处要在代码末尾添加return *this
,返回类型写成自己类的引用。
7. 堆空间和栈空间的比较:
(1)堆空间比栈空间大很多,因此如果要创建很大的临时空间,使用堆空间比较不容易达到空间上限。
(2)栈空间创建和销毁由程序自己完成。堆空间创建和销毁要由代码明确创建和销毁,不然会造成内存泄漏问题。
(3)如果创建的数组变量大小不确定,那么使用堆空间来动态创建会比较不浪费空间。