浅拷贝如何解决:
- 深拷贝----让每个对象都拥有自己独立的资源—拷贝的不是对象本身的内容,而是对象管理资源中的内容
a传统版解决办法,对产生对象的函数都进行深拷贝的操作
b.现代版的解决办法,代码量少,提高了代码的复用率
2.在浅拷贝的基础上,加上引用计数的方法,再加上写时拷贝,就大概可以实现浅拷贝的问题
但是不建议写这种写是拷贝的代码,因为在所有的进行写操作或者,push_back操作的代码中都有可能需要进行空间的分离,并且在单线程下面还好,多线程下又有安全问题。所以,还是别写了,知道就行了。
//模拟实现简单的string类
//关于memset()函数:memset函数是按照字节来设置元素的假如你要设置的是int类型的数组,那么不好意思设置不了
class string
{
friend ostream& operator<<(ostream& _cout, const string& p);
public:
typedef char* iterator; //迭代器
public:
string(char* str = "")
{
if (str == nullptr)
str = "";
_size = strlen(str);
_capacity = strlen(str);
_str = new char[strlen(str) + 1];
strcpy(_str, str);
}
string(const char s, int n)
{
_size = n;
_capacity = n; //这里的容量没有+1,也就是说没有算最后的'\0',这一切都是为了遵循,string本来的面貌
_str = new char(n + 1);
for (int i = 0; i < n; ++i)
_str[i] = s;
_str[n] = '\0';
}
string(const string& p)
:_str(p._str)
, _size(p._size)
, _capacity(p._size) //按理来说这里给出的空间的大小应该是p._capacity但是害怕p中有很大的容量,但是p中的有效元素却只有几个的情况下,所以直接按照size+1的大小来赋值,等到容量不够再扩容
{
_str = new char[p._size + 1];
strcpy(_str, p._str);
}
string& operator= (const string& p)
{
if (this != &p)
{
delete[] _str;
_str = new char[strlen(p._str) + 1];
strcpy(_str, p._str);
_size = strlen(p._str);
_capacity = strlen(p._str);
}
return *this;
}
char& operator[](int x)const
{
assert(x < _size);
return _str[x];
}
char& operator[](int x)
{
assert(x < _size);
return _str[x];
}
~string()
{
if (_str)
{
delete[] _str;
_str = nullptr;
}
}
/
int size()const
{
return _size;
}
int capacity()const
{
return _capacity;
}
bool empty()const
{
return (_size == 0);
}
//
void resize(int newsize, char c)
{
int oldsize = _size;
if (oldsize < newsize) //如果之前空间的有效长度小于你现在要扩展到的有效长度,那么就先看是否需要扩容
{
if (_capacity < newsize) //如果需要扩容
{
reserve(newsize);
}
memset(_str + _size, c, newsize - oldsize); //扩完容再填充
}
_size = newsize; //最后无论哪种情况都会走到下面
_str[_size] = '\0';
}
void reserve(int size)
{
if (_capacity < size)
{
char* temp = new char[size + 1];
strcpy(temp, _str);
delete[] _str;
_str = temp;
_capacity = size;
}
}
/
void push_back(char ch)
{
if (_capacity == _size)
{
tow_capacity();
}
_str[_size++] = ch;
_str[_size] = '\0';
}
string& operator+=(char ch)
{
push_back(ch);
return *this;
}
string& operator+=(char* ch)
{
while (((size_t)_size + strlen(ch)) > (size_t)_capacity) //这里我转size_t纯属是为了消除警告:无符号与有符号不匹配
{
tow_capacity();
}
_str = strcat(_str, ch);
_size = _size + strlen(ch);
return *this;
}
/
int find(char c)
{
for (int i = 0; i < _size; ++i)
{
if (c == _str[i])
return i;
}
return npos;
}
int find(char* c)
{
int flag = 0;
int i;
for (i = 0; i < _size; ++i)
{
if (c[0] == _str[i])
{
for (int j = i; j < strlen(c)&&j<_size; ++j)
{
if (c[j] != _str[j])
{
flag = 1;
break;
}
}
if (flag != 1)
return i;
}
flag = 0;
}
return npos;
}
int rfind(char c)
{
for (int i = _size - 1; i >= 0; --i)
{
if (c == _str[i])
return i;
}
return npos;
}
int rfind(char* c)
{
int flag = 0;
int i;
for (i = _size - 1; i >= 0; --i)
{
if (c[0] == _str[i])
{
for (int j = i; j < strlen(c) && j<_size; ++j)
{
if (c[j] != _str[j])
{
flag = 1;
break;
}
}
if (flag != 1)
return i;
}
flag = 0;
}
return npos;
}
string(char* begin,char* end)
{
_size = end - begin;
_capacity = _size;
_str = new char[_size + 1];
strncpy(_str, begin, _size);
}
string substr(int pos = 0,int end = npos) //为了写这种方法还要专门给出一种构造函数,为的就是临时对象在离开作用域时候就被销毁
{
if (end == npos)
end = _size;
string strtemp(_str + pos, _str + pos + (end - pos+ 1)); //截取的区间长度,+1的原因是你举个例子试试就知道了
return strtemp;
}
const char* c_str()const
{
return _str;
}
/
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size;
}
private:
void tow_capacity() //检测是否需要扩容
{
reserve(_capacity * 2);
}
private:
char* _str;
int _size;
int _capacity;
static int npos;
};
int string::npos = -1;
ostream& operator<<(ostream& _cout, const string& p)
{
for (int i = 0; i < p._size; ++i)
{
_cout << p[i];
}
return _cout;
}
void test()
{
string s1("123456");
string s2(s1);
string s3;
s3 = s2;
cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
cout << s2.capacity() << endl;
s2.reserve(10);
cout << s2.capacity() << endl;
s2.resize(15, '!');
cout << s2 << endl;
s2.push_back('w');
cout << s2 << endl;
s2 += 'o';
cout << s2 << endl;
s2 += "rld";
cout << s2 << endl;
s2 += "大河向东流呀!天上的星星参北斗呀!说走咋就走呀,你有我有全都有呀!";
cout << s2 << endl;
cout << s2.find('o') << endl;
cout << s2.rfind('o') << endl;
cout << s2.find("world") << endl;
cout << s2.rfind("world") << endl;
cout << s2.find("hello") << endl;
cout << s2.rfind("hello") << endl;
cout << s2.substr(15, 19) << endl;
}
在自定义类型中,加入想要使用范围for那么就必须给出begin()和end()两个函数,不然就没有办法使用,
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size;
}
类私这样的函数,就是得到首位地址的函数