前言

有了基本的构造函数、拷贝函数、析构函数
可以自己试着写个丐版的string。


正文

  1. hstring str(“哈哈哈”); //构造函数
  2. hstring strA(str); //拷贝函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#pragma once
class hstring{
public:
hstring(){

}

hstring(const hstring &hs){

}

~hstring(){

}
};

大概框架就是这样,但是要注意,套string就没意思了。
char或者char*的话要注意内存分配的事。

想了下大概是char*比较合适,毕竟初始化的时候鬼知道这个字符串多长。
然后提到长度,还要写个成员变量,和成员函数去统计出这个长度。


构造

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#pragma once
class hstring{
private:
char *c_str;
unsigned int len;
unsigned int Length(const char *hs){
while (hs[this->len++]);
return this->len;
}
public:
hstring(){
this->len = 0;
}

hstring(const char* hs){
c_str = new char[Length(hs)];
for (int i = 0; i < this->len; i++){
c_str[i] = hs[i];
}
}

char *toShow(){
return c_str;
}

unsigned int toLength(){
return this->len;
}

~hstring(){
delete[] c_str;
}
};

1
2
3
4
5
6
7
8
9
#include<iostream>
#include"hstring.h"

int main(){
hstring str("hahah");
std::cout << str.toShow() << std::endl;

return 0;
}

因为没涉及到重载,只能通过成员函数先打印将就一下了。

结果也是ok的,至于那个toLength是因为我记得string好像也有个调用可以显示长度的方法,就干脆放在public下面调用得了。
至于len本质上是存放长度肯定不希望被其他人调用就放在私有里面,然后Length的话,本质上跟sizeof有点相似,它会计算字符串结尾的\0,想要strlen的效果就让返回值-1就行了。

至于中文占2个字节的问题先不考虑。

到这里构造没啥事了,下面就是拷贝的问题。


拷贝

拷贝就难在没有[]重载运算。hstring是自己定义的类。
你要想让hstring strA(str); 还要注意不能让两个地址相同,不然前面的被释放了,后面的就无效了。

1
2
3
hstring(const hstring &hs){
c_str = hs;
}

这样肯定行不通,c_str是char*类型,hs是hstirng类型的,强转上逻辑也不对,因为没有调出hs.c_str这种东西。

使用列表传递的话,就要再次调用toShow函数,但是这里的hs是const类型,所以toShow也要加上const

1
2
3
4
5
6
hstring(const hstring &hs):hstring(hs.toShow()){
//c_str = hs;
}
char *toShow() const{
return c_str;
}

这样编译是通过了,但是要看看效果。

看到效果ok。


印证

最后无非就是印证销毁的时候strA还是不是正常的。
这个讲道理是不好印证的,因为str先声明的,strA后声明的,你也没办法指定它执行析构函数,这个还是由编译器认的。

所以顺序上没法印证,那就只能通过改变str,查看strA的结果还是否相同,去印证是不是一个内存地址。

1
2
3
4
5
6
7
void toRemake(const char *hs){
delete[] c_str;
c_str = new char[Length(hs)];
for (int i = 0; i < this->len; i++){
c_str[i] = hs[i];
}
}

还是老样子传递const char*, 然后先释放原有的内存,因为不能保证c_str是否之前分配过了,然后在赋予新的内存。老样子循环抄写hs,这里用不用memcpy都随便。

效果不同,说明strA和str使用的不是同一个内存。


完整的hstring.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#pragma once
#include<iostream>
class hstring{
private:
char *c_str;
unsigned int len=0;
unsigned int Length(const char *hs){
while (hs[this->len++]);
return this->len;
}
public:
hstring(){
}

hstring(const char* hs){
c_str = new char[Length(hs)];
for (int i = 0; i < this->len; i++){
c_str[i] = hs[i];
}
}

hstring(const hstring &hs):hstring(hs.toShow()){
//c_str = hs;
}

char *toShow() const{
return c_str;
}

unsigned int toLength(){
return this->len;
}

void toRemake(const char *hs){
delete[] c_str;
c_str = new char[Length(hs)];
for (int i = 0; i < this->len; i++){
c_str[i] = hs[i];
}
}

~hstring(){
delete[] c_str;
}
};

结语

优化空间肯定还有的,重载就是一个点。
还有就是功能上还是丐版阶段。