对象的浅拷贝和深拷贝
#include <iostream>
using namespace std;
class SeqStack
{
public:
SeqStack(int size = 10) :_size(size),_top(-1)
{
_pstack = new int[size];
}
~SeqStack()
{
delete[] _pstack;
_pstack = nullptr;
}
bool isEmpty()
{
return _top == -1;
}
bool isFull()
{
return _top == _size - 1;
}
void push(int val)
{
if (isFull())
resize();
_pstack[++_top] = val;
}
void pop()
{
if (isEmpty())
return;
_top--;
}
int top()
{
return _pstack[_top];
}
private:
int* _pstack;
int _top;
int _size;
void resize()
{
int* tmp = new int[_size * 2];
for (int i = 0; i < _size; i++)
{
tmp[i] = _pstack[i];
}
delete[]_pstack;
_pstack = tmp;
_size *= 2;
}
};
int main()
{
SeqStack s1;
SeqStack s2(s1);
SeqStack s3 = s1;
return 0;
}
运行上面的代码,程序会发出这样的错误。
在调试定位错误的时候发现,它是在main函数执行结束调用SeqStack析构函数时引起的。
在定义一个类时,如果我们没有写自己的构造析构函数,系统会自动给我们生成默认的构造析构函数,其中就包括拷贝构造函数。
而系统默认的拷贝构造函数是内存拷贝,也就是浅拷贝,在执行这行指令 SeqStack s2(s1);时,调用SeqStack的拷贝构造函数,把s1成员的值直接拷贝一份给s2, SeqStack s3 = s1;同理。
这时就有了三个指针指向s1的成员_pstack所指向的内存。

在main执行完毕时,会依次调用s3、s2、s1的析构函数,而他们的_pstack指针都指向同一块内存,p3析构函数执行结束后,这块内存已经被释放了,s2和s1的_pstack就成了野指针,对野指针delete时,自然就会引发程序崩溃,这就是对象浅拷贝所带来的隐患。
对象浅拷贝并不一定会出现错误,但是在占用外部资源的情况下,那浅拷贝一定会出现问题。
在对象占用外部资源的情况下,比如成员中有指针,并且这个指针指向的是一块new出来的内存,这时候我们就需要深拷贝来实现自己的拷贝构造函数。
系统默认生成的拷贝构造函数是这样的:
SeqStack(const SeqStack& s)
{
_pstack = s._pstack;
_size = s._size;
_top = s._top;
}
直接把指针的值赋给新对象。
深拷贝的自定义拷贝构造函数:
SeqStack(const SeqStack& s)
{
_pstack = new int[s._size];
for (int i = 0; i <= s._top; i++)
{
_pstack[i] = s._pstack[i];
}
_size = s._size;
_top = s._top;
}
出除了拷贝构造会出现浅拷贝问题,赋值构造函数(operator=)也会出现,除了浅拷贝的隐患,还有就是内存泄露的问题,我们也需要重新定义赋值构造函数实现深拷贝。
SeqStack& operator=(const SeqStack& s)
{
if (this == &s)
return *this;
delete[] _pstack;
_pstack = new int[s._size];
for (int i = 0; i <= s._top; i++)
{
_pstack[i] = s._pstack[i];
}
_size = s._size;
_top = s._top;
return *this;
}
7158

被折叠的 条评论
为什么被折叠?



