作者:小 琛
欢迎转载,请标明出处
string中的拷贝构造
#include <iostream>
namespace K
{
class string
{
public:
//构造函数
string(const char* str = " ")
:_size (strlen(str))
{
_capacity = _size;
_str = new char[_capacity + 1];//在堆上开辟一块,可以完成修改等操作
}
//析构函数
~string()
{
std::cout << _str << std::endl;
delete[] _str;
_str = nullptr;
}
private:
char* _str;
size_t _size;
size_t _capacity;
};
而对于上面的类,我们不进行自定义,使用编译器自定义的拷贝构造函数,进行测试发现如下问题:
int main()
{
K::string s1("hello");
K::string s2(s1);
return 0;
}
经过调试发现,程序在进行s1的析构时候崩溃,为什么呢?
浅拷贝与深拷贝
-
浅拷贝
也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以 当继续对资源进项操作时,就会发生发生了访问违规。
实际到该例子中就是:s2将s1的值按位全部拷贝过来,因而s1._str与s2_str指向同一块内存,在析构的时候,同一块内存被重复释放,导致程序崩溃
-
深拷贝
给每个对象分配独立的资源,保证多个对象不会因为共享资源而导致的内存多次释放的错误
代码实现
#include <iostream>
namespace K
{
class string
{
public:
//构造函数
string(const char* str = " ")//不能将str的缺省值设定为nullptr,会令strlen崩
:_size (strlen(str))
{
_capacity = _size;
_str = new char[_capacity + 1];//在堆上开辟一块,可以完成修改等操作
strcpy(_str, str);
}
//深拷贝
string(const string& s1)
{
_str = new char[s1._size + 1];
strcpy(_str, s1._str);
_size = s1._size;
_capacity = s1._capacity;
}
string& operator=(const string& s1)
{
if (this != &s1)//要加检查,否则自己给自己赋值容易出现随机值
{
char* tmp = new char[s1._size + 1];
strcpy(tmp, s1._str);
delete[] _str;
_str = tmp;
_size = s1._size;
_capacity = s1._capacity;
}
return *this;
}
//析构函数
~string()
{
std::cout << _str << std::endl;
delete[] _str;
_str = nullptr;
}
char& operator [](size_t pos)
{
return _str[pos];
}
private:
char* _str;
size_t _size;
size_t _capacity;
};
}