运算符重载之深copy

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运算符的理解;https://docs.microsoft.com/zh-cn/cpp/cpp/new-and-delete-operators?view=vs-2019

猜你喜欢

转载自www.cnblogs.com/IvanKeller/p/10841036.html
今日推荐