拷贝构造和赋值重载的实践
大约 3 分钟
拷贝构造和赋值重载的实践
这个类的对象的成员变量有占用外部资源,所以我们要重写它的拷贝构造函数和赋值函数。
实现String类型
#include <iostream>
using namespace std;
class String
{
public:
String(const char* str = nullptr)//普通构造函数
{
if (str != nullptr)
{
m_data = new char[strlen(str) + 1];//'\0'要算上
strcpy(this->m_data, str);
}
else//用户传进来的字符串是空的话 ,为了让其他方法不用判空
{
m_data = new char[1];//new char;开辟1个字节大小的空间
*m_data = '\0';//0
}
}
String(const String& other)//拷贝构造函数,深拷贝
{
m_data = new char[strlen(other.m_data) + 1];
strcpy(m_data, other.m_data);
}
~String(void)//析构函数
{
delete[]m_data;
m_data = nullptr;//防止野指针的出现
}
//使用String&是为了支持连续的operator=赋值操作
String& operator=(const String& other)//赋值重载函数,深拷贝
{
if (this == &other)//防止自赋值
{
return *this;//str1
}
delete[]m_data;//释放当前的外部资源
m_data = new char[strlen(other.m_data) + 1];
strcpy(m_data, other.m_data);
return *this;//str1
}
private:
char* m_data;//用于保存字符串
};
int main()
{
//用带const char*参数的构造函数
String str1;//调用默认的构造,形参是nullptr
String str2("hello");
String str3 = "world";//str2
//调用拷贝构造函数
String str4 = str3;
String str5(str3);
//调用赋值重载函数
/*
str1 = str2
str1.operator=(str2) => str1
str3 = str1
*/
str3 = str1 = str2;
return 0;
}
实现循环队列queue

- 如果是用顺序表实现队列,那么现在,不能入队了,因为已经满了,前面有元素出队,但是没办法放。
- rear++的时候,我们不要让他加到末尾,让他加到前面去;
- 包括front也一样,把78出队后,回到队前面
#include <iostream>
using namespace std;
//循环队列 memcpy realloc
class Queue
{
public:
Queue(int size = 5)//构造函数
{
_pQue = new int[size];
_front = _rear = 0;
_size = size;
}
//Queue(const Queue&) = delete;
//Queue& operator=(const Queue&) = delete;
Queue(const Queue& src)//拷贝构造函数
{
_size = src._size;
_front = src._front;
_rear = src._rear;
_pQue = new int[_size];
for (int i = _front;
i != _rear;
i = (i + 1) % _size)
{
_pQue[i] = src._pQue[i];
}
}
Queue& operator=(const Queue& src)//赋值函数
{
//防止自赋值
if (this == &src)
return *this;
delete[]_pQue;
_size = src._size;
_front = src._front;
_rear = src._rear;
_pQue = new int[_size];
for (int i = _front;
i != _rear;
i = (i + 1) % _size)
{
_pQue[i] = src._pQue[i];
}
return *this;
}
//析构函数
~Queue()
{
delete[]_pQue;
_pQue = nullptr;
}
//入队操作,队尾入
void push(int val)
{
if (full())
resize();
_pQue[_rear] = val;//队尾赋值
_rear = (_rear + 1) % _size;//因为是循环队列
}
//出队操作
void pop()
{
if (empty())
return;
_front = (_front + 1) % _size;
}
//获取队头元素
int front()
{
return _pQue[_front];
}
bool full() { return (_rear + 1) % _size == _front; }//判满
bool empty() { return _front == _rear; }//判空
private:
void resize()//扩容操作
{
int* ptmp = new int[2 * _size];
int index = 0;
for (int i = _front; i != _rear; i = (i + 1) % _size)
{
ptmp[index++] = _pQue[i];
}
delete[]_pQue;
_pQue = ptmp;
_front = 0;
_rear = index;
_size *= 2;
}
int* _pQue;//申请队列的数组空间,方便扩容
int _front;//指示队头的位置
int _rear;//指示队尾的位置
int _size;//队列扩容的总大小
};
int main()
{
Queue queue;
for (int i = 0; i < 20; ++i)
{
queue.push(rand() % 100);
}
while (!queue.empty())
{
cout << queue.front() << " ";
queue.pop();
}
cout << endl;
Queue queue1 = queue;
queue1 = queue;
return 0;
}