学习要点:
1 学习这个stack类的定义和使用。
2 拷贝操作符函数 = ,和什么时候需要重写拷贝操作符函数。
3 切记不可以用memcpy来对string数组进行拷贝,因为string对象中的字符串是存放在堆中,memcpy会导致浅拷贝,引起多次释放的问题.
#include <iostream>
using namespace std;
typedef string T;
typedef unsigned int unit;
class Stack
{
T *mem;//string 类型指针 使用new 来初始化
unit max;
unit len;
public:
Stack(unit n):mem(new T[n]), max(n), len(0) {}
//拷贝构造函数 创建空间 max和拷贝的空间一样大
Stack(Stack &s):max(s.max),len(0),mem(new T[s.max])
{
}
~Stack(){delete[] mem;}
unit max_size() const {return max;}
unit size() const{return len;}
Stack& push(const T& e)
{
if(len >= max) throw 1;
else mem[len++] = e;
return *this;
}
T pop(T& e)
{
if(len ==0 ) throw 0;
return mem[--len];
}
void print() const
{
for(int i = 0; i< len; i++)
{
cout << mem[i] << "|";
}
cout << endl;
}
//复制操作符号 删掉以前到数据 复制新的进来
Stack& operator=(const Stack& s)
{
if(this == &s) return *this; //考虑自己给自己赋值的情况 这种情况在交换两个数中可能出现
delete[] mem; //删掉原来的
string *temp = new T[s.max];
len = s.len;
for(int i =0; i< len;i++)
{
mem[i] = s.mem[i];
}
return *this;
}
};
int main()
{
Stack s1(5);
//s1.push(1);
//要想这样 必须push()的返回值为Stack对象引用类型的。
s1.push("hello").push("good morning").push("早安");
s1.print();
// 谨防浅拷贝 Stack s2(s1); 重复释放错误 提示:段错误 (核心已转储)
//所以重写了拷贝构造函数 给自己的mem分配空间
Stack s2(s1);
s2.print();
s2.push("杨强").push("芙蓉");
s2.print();
// 复制函数 也要谨防浅拷贝
//
s1 = s2;
cout << "s1 = s2之后 print" <<endl;
s1.print();
//如果你的程序所有的属于已完成。但弹出了 这一般是析构函数的问题。
//提示了两次释放
/*
glibc detected *** ./a.out: double free or corruption (fasttop): 0x0809e078 ***
======= Backtrace: =========
/lib/libc.so.6(+0x6c501)[0x17c501]
/ lib/libc.so.6(+0x6dd70)[0x17dd70]
*/
}
/*
总结:
一般有指针成员指向动态内存的时候,默认的拷贝构造函数和赋值函数都会简单地将指针复制一份,
这会带来多次释放的问题。
所以有指针成员指向动态内存的时候需要
自己写 拷贝构造函数 赋值函数(operator=) 析构函数
*/