string类的简单模拟实现,不需要太复杂,这里主要考察的是深浅拷贝
我们需要创造一个命名空间用于区分标准库里面的string类这里我们用lt来表示
namespace lt
{
class string
{
private:
char* _str;
};
};
string类中将变量类型私有,公有一些接口用于获得里面的数据,这样子体现了C++中的封装性,还要写默认构造函数以便于将类实例化为对象
namespace lt
{
class string
{
public:
//string(char* str)
// :_str(new char[strlen(str) + 1])
//{
// strcpy(_str, str);
//}
//string()
// :_str(new char[1])//创建一个空间不用于存放有效字符,只是用于存放标识字符
//{
// _str[0] = '\0';
//}
string(const char* str = "")//这个整合了上面两种情况,传空值和传字符串,
:_str(new char[strlen(str) + 1])
{
strcpy(_str, str);
}
size_t size()
{
return strlen(_str);
}
char& operator[](size_t i)
{
return _str[i];
}
~string()
{
delete[] _str;
_str = nullptr;
}
char* c_str()
{
return _str;
}
private:
char* _str;
};
};
在命名空间中再写测试函数test_string1,用于检测我们的构造函数是否正确,还要写一个获取大小的函数,用于遍历、析构函数用于释放空间避免内存泄露,[]是用于遍历,c_str用于返回c语言习惯中的字符指针。
void test_string1()
{
lt::string s1("hello");//
lt::string s2;
for (size_t i = 0; i < s1.size(); i++)
{
cout << s1[i] << " ";
}
cout << endl;
for (size_t i = 0; i < s2.size(); i++)
{
cout << s2[i] << " ";
}
cout << endl;
for (size_t i = 0; i < s1.size(); i++)
{
s1[i] += 1;
cout << s1[i] << " ";
}
cout << endl;
}
默认函数成员函数中还有拷贝构造和赋值运算符重载没有写,他会默认浅拷贝,这里如果浅拷贝的话就会导致报错,因为浅拷贝也叫值拷贝,如果用字符串去拷贝构造的话,他们会指向同一个数据段的首字符,当调用析构函数时会释放两次,导致报错
这里就要自己写拷贝构造和赋值运算符
string(const string& str)//深拷贝
:_str(new char[strlen(str._str)+1])
{
strcpy(_str, str._str);
}
string& operator=(const string& str)
{
if (this != &str)//避免出自己给自己赋值
{
char* deletespace = _str;
delete[] deletespace;
_str = new char[strlen(str._str) + 1];
strcpy(_str, str._str);
}
return *this;
}
将这个命名空间合体就是
//namespace lt
//{
// class string//简单的string类
// {
// public:
// //string(char* str)
// // :_str(new char[strlen(str) + 1])
// //{
// // strcpy(_str, str);
// //}
// //string()
// // :_str(new char[1])
// //{
// // _str[0] = '\0';
// //}
// string(const char* str = "")
// :_str(new char[strlen(str) + 1])
// {
// strcpy(_str, str);
// }
//string(const string& str)//深拷贝
// :_str(new char[strlen(str._str)+1])
//{
// strcpy(_str, str._str);
//}
//string& operator=(const string& str)
//{
// if (this != &str)//避免出自己给自己赋值
// {
// char* deletespace = _str;
// delete[] deletespace;
// _str = new char[strlen(str._str) + 1];
// strcpy(_str, str._str);
// }
// return *this;
//}
//size_t size()
//{
// return strlen(_str);
//}
//char& operator[](size_t i)
//{
// return _str[i];
//}
//~string()
//{
// delete[] _str;
// _str = nullptr;
//}
//char* c_str()
//{
// return _str;
//}
//private:
// char* _str;
//};
//void test_string1()
//{
// lt::string s1("hello");//
// lt::string s2;
// for (size_t i = 0; i < s1.size(); i++)
// {
// cout << s1[i] << " ";
// }
// cout << endl;
// for (size_t i = 0; i < s2.size(); i++)
// {
// cout << s2[i] << " ";
// }
// cout << endl;
// for (size_t i = 0; i < s1.size(); i++)
// {
// s1[i] += 1;
// cout << s1[i] << " ";
// }
// cout << endl;
//}
// void test_string2()//测试浅拷贝和深拷贝
// {
// lt::string s1("hello");
// lt::string s2(s1);
// cout << s1.c_str() << endl;
// cout << s2.c_str() << endl;
// lt::string s3("world");
// s1 = s3;
// lt::string s4 = s3;
// cout << s1.c_str() << endl;
// cout << s3.c_str() << endl;
// cout << s4.c_str() << endl;
//
// }
//}