Item:
先考虑测试用例, 从测试用例考虑函数实现
如果 class with pointer 那么 BigThree 都要自己重新写, 不能用编译器自带的.
- 拷贝构造函数 copy constructor
- 析构函数 Destructor
- 拷贝赋值函数(运算符) copy assignment operator
使用 new( ) 分配内存,则需要用 delete( )在相同的作用域内对应搭配,防止内存泄露;
Detail: Effective C++ Item16: Use the same form in corresponding uses of new and delete.new( ): distribute memory -> call ctor
delete( ): call dtor -> free memory
array new 需要搭配 array delete: 否则引起内存泄露: 只调用了 p 的 dtor, 无法调用 p+1, p+2 的 dtor, 而母体块已经 free 掉.
Code:
string *p = new string[3]; ... delete p[];
operator= : 检测自我赋值 -> delete 原有 -> new 足够空间 -> copy
检测自我赋值: 防止delete后访问,导致未定义行为!
Detail: Effective C++ Item11: Handle assignment to self in operator=令 operator= 返回一个 reference to *this : 实现“连锁赋值”
Detail: Effective C++ Item10: Have assignment operators return a reference to *this
Task:
Realize string, a class without pointer member, including merbers as following:
- private member 1: char* m_data
- public member 1: constructer: String(const char* ctr = 0);
public member 2: Big Three:
- String(const String&);
- ~String( );
- String& operator = (const String&) ;
public member 3: support function: char* get_c_str() to support output operator
Some global functions to use String: out put operator >>;
Code:
// myString_test.cpp
// Item1: test case -> function realization
#include <iostream>
#include "myString.h"
int main()
{
String str1;
String str2("Hello");
std::cout << str1 << std::endl;
std::cout << str2 << std::endl;
str1 = str2;
String str3(str2);
std::cout << "str1:" << str1 << std::endl;
std::cout << "str2:" << str2 << std::endl;
std::cout << "str3:" << str3 << std::endl;
return 0;
}
// myString.h
#ifndef MY_STRING_H
#define MY_STRING_H
class String;
class String
{
public:
String(const char* cstr = 0);
String(const String& str);
String& operator = (const String& str);
~String();
char* get_c_str() const { return m_data; }
private:
char* m_data;
};
#include <cstring>
// Item2: Big Three : copy constructor / destructer / copy assignment operator
inline
String::String(const char* cstr)
{
if (cstr) {
m_data = new char[strlen(cstr) + 1];
strcpy(m_data, cstr);
}
else { // no initialization value
m_data = new char[1];
*m_data = '\0';
}
}
inline
String::~String()
{
delete [] m_data; // Item3: array new <-> array delete
}
inline
String::String(const String& str)
{
m_data = new char[strlen(str.m_data) + 1];
strcpy(m_data, str.m_data);
}
inline String&
String::operator = (const String& str) // & after typename: reference
{
// self assignment
if(this == &str) // & before object: address of
return *this;
delete[] m_data;
m_data = new char[strlen(str.m_data) + 1];
strcpy(m_data, str.m_data);
return *this; // *this / str is a String
}
inline std::ostream&
operator << (std::ostream& os, const String& str)
{
os << str.get_c_str();
return os;
}
#endif