- P436 C++ Primer Plus(第六版)
- #define _CRT_SECURE_NO_WARNINGS
- #include <iostream>
- using namespace std;
- class Cp
- {
- public:
- static int sta1,
- sta2,
- sta3,
- sta4;
- char *c;
- int len;
- Cp(const char* st = "no")
- {
- sta1++;
- cout <<"默认构造 =" << sta1 << "; 总构造 =" << sta1 + sta2 << ";" << endl;
- len = strlen(st);
- c = new char[len + 1];
- strcpy(c, st);
- }
- Cp(const Cp& p)
- {
- sta2++;
- cout << "copy 构造 =" << sta2 << "; 总构造 =" << sta1 + sta2 << ";" << endl;
- len = p.len;
- c = new char[len + 1];
- strcpy(c, p.c);
- }
- ~Cp()
- {
- sta3++;
- cout << this->c << "'~Cp" << sta3 << ":" << endl;
- delete[] c;
- }
- Cp& operator= (Cp& p)
- {
- sta4++;
- cout << "赋值:" << sta4 << endl;
- if (this == &p)
- return *this;
- delete[] c;
- len = p.len;
- c = new char[len + 1];
- strcpy(c, p.c);
- return *this;
- }
- };
- int Cp::sta1 = 0;
- int Cp::sta2 = 0;
- int Cp::sta3 = 0;
- int Cp::sta4 = 0;
- int main()
- {
- {
- Cp p1("aas");
- //Cp p2 = Cp(p1);
- //Cp p3 = p1;
- Cp p4;
- p4 = p1;
- char b[4] = "bcc";
- p4.c = b;// 让 p4.c 指向栈区的空间 // 改为 strcpy (p4.c, b);
- cout << p1.c << endl;
- }
- system("pause");
- return 0;
- }
运行上面的代码将会出错, 如下:
这是因为, p4.c = b;// 让 p4.c 指向栈区的空间, 第一次调用析构函数时, 企图释放栈区空间; 所以将这个语句改为 strcpy (p4.c, b); 即可正确运行 (这是个插曲, 嘿嘿), 下面看看关于 =(赋值运算符) 重载函数里的内容: 书中 (C++ Primer Plus) 使用 delete[] c; c = new char[len + 1]; 这两条语句让我很不解, 为什么要 delete 后, 再重新给它 new 一块相同大小(大小已经不同了, 后面才想到~~) 的空间呢? 为何不将这两条语句去掉呢? 那就实验一下, 将这两条语句注释掉后, 结果如下:
问题发生在第一次调用析构函数时,(思考中~~)
终于发现了猫腻, 创建 p4 的时候给 p4.c new 的是多少空间呢? strlen("no") + 1; 是 3 个字节的空间, 但是 = 重载中, strcpy(c, p.c); 将 4 字节的内容 copy 到了 c 指向的空间中 (strcpy 的危险表露无疑~~), 已经越界操作内存, 所以报错; 因此赋值运算符函数中重新获得 len 的值, 销毁原空间(防止内存泄漏) 并重新 new 足够的空间;
归根结底还是 new, delete 运算符的理解;
来源: http://www.bubuko.com/infodetail-3053095.html