【C++】拷贝构造函数、赋值重载函数、深拷贝及浅拷贝 模拟实现顺序栈和环形队列的问题及理解

【C++】拷贝构造函数、赋值重载函数、深拷贝及浅拷贝 模拟实现顺序栈和环形队列的问题及理解

拷贝构造函数:用已有对象初始化新对象。

Person p2(p1) Person p2 = p1

赋值运算符:将已有对象赋值给另一个已存在的对象 p1=p2

浅拷贝:只复制指针值,共享内存 默认的拷贝/赋值行为

深拷贝:复制指针指向的内容,独立内存 需要自定义实现

!!!总结:只要类中有动态分配的内存(new),就必须实现:

·拷贝构造函数(深拷贝) 创建新的对象

·赋值运算符重载(深拷贝) 给已存在的对象赋值

拷贝构造vs赋值重载

// 拷贝构造:创建新对象

SeqStack s1;

SeqStack s2 = s1;// ←拷贝构造(s2是新对象)

SeqStack s3(s1);// ←拷贝构造(s3是新对象)

// 赋值重载:已存在的对象赋值

SeqStack s1;

SeqStack s2;// s2已经存在

s2 = s1;// ←赋值重载(s2已存在)

// 关键区别:

// 拷贝构造:不需要释放旧资源(新对象没有)

// 赋值重载:需要释放旧资源(对象已有资源)

·析构函数(释放资源)

浅拷贝:Eg:

class Person { public: Person(const char* name, int age) { this->name = new char[strlen(name) + 1]; strcpy(this->name, name); this->age = age; } ~Person() { delete[] this->name; // 释放内存 } private: char* name; int age; }; int main() { Person per1("赵云", 23); Person per2(per1); // 使用默认拷贝构造函数(浅拷贝) // 问题:per1和per2的name指针指向同一块内存 // 析构时同一块内存被释放两次 → 程序崩溃! return 0; }

深拷贝:Eg:

class Person { public: // 构造函数 Person(const char* name, int age, char sex) { this->name = new char[strlen(name) + 1]; strcpy(this->name, name); this->age = age; this->sex = sex; } // 拷贝构造函数:深拷贝 // 参数必须是引用,否则会无限递归 Person(const Person& rhs) { cout << "Person(const Person& rhs)" << endl; // 重新开辟独立的内存空间 this->name = new char[strlen(rhs.name) + 1]; strcpy(this->name, rhs.name); this->age = rhs.age; this->sex = rhs.sex; } // 析构函数 ~Person() { delete[] this->name; this->name = nullptr; } private: char* name; int age; char sex; }; int main() { Person per1("赵云", 23, 'M'); Person per2(per1); // 调用拷贝构造函数,深拷贝 // per1和per2的name指向不同的内存,互不影响 return 0; }

模拟实现顺序栈和环形队列遇到的问题总结:

  1. 模拟实现堆:mTop始终指向栈顶元素的下一个元素,因此出栈直接mTop--,就是指向栈顶元素假装此位置为空没有元素,伪删。
  2. 判满:bool full() { return mTop == mSize; } // 元素个数 == 容量,因为mTop刚好指向下一个元素,所以数值上可以和mSize相比。

3.模拟实现和环形队列:front_:指向队头元素(第一个有效元素)

rear_:指向队尾的下一个位置(下一个要放的位置)

4.,环形移动:

// 入队:rear_ 环形后移 void push(int data) { queue_[rear_] = data; rear_ = (rear_ + 1) % size_; // 取模实现环形 } // 出队:front_ 环形后移 void pop() { front_ = (front_ + 1) % size_; // 取模实现环形 }

5.判满(rear_ + 1) % size_ == front_

浪费一个空间的原因是区分空和满。

6.!!!扩容时为什么 rear_ = count?

因为扩容前队列的环形的 rear可能在front前,顺序不对,而扩容之后赋值过程中count的增加suoyinindex从front开始,此时队列变成顺序的,因此rear刚好在count的位置。