1. 浅拷贝和深拷贝——对象和类
浅拷贝
浅拷贝只复制对象的基本属性,而不复制引用类型的属性指向的对象,即只复制引用而不复制引用指向的对象
-
在浅拷贝中,新对象与原始对象共享引用类型的属性指向的对象,即它们指向同一个对象。
-
编译器提供的拷贝构造函数是浅拷贝,当一个对象修改了内存的数据,会影响到另一个对象。
-
如果在析构函数释放内存,A释放了内存,那么B就成了野指针,发生不可预知的错误。
深拷贝
- 深拷贝会复制对象的所有属性,包括基本类型和引用类型的属性,以及引用类型的属性指向的对象,以确保新对象与原始对象完全独立。
- 在深拷贝中,复制引用类型的属性指向的对象,而不是简单地复制引用。
- 深拷贝创建的对象与原始对象之间没有任何关联,修改一个对象不会影响另一个对象。
深拷贝的拷贝构造函数需要这么写:
class CGirl
{
string m_name;
int m_age;
int* m_ptr;
CGirl(){m_name.clear();m_age=0;m_ptr=nullptr;}
// 深拷贝 重载默认的拷贝构造函数
CGirl(const CGirl& gg)
{
m_name = gg.m_name;m_age = gg.m_age;
m_ptr = new int; // 分配内存
memcpy(m_ptr,gg.m_ptr,sizeof(int)); // 拷贝数据
}
};
深拷贝的赋值函数会在下面进行实现。
2. 嵌套和递归使用模板类
这个内容是比较重要的!标准模板库都是要用到这个知识,经常嵌套或递归使用。
在C++11之前,嵌套使用模板类的时候,> >之间要加空格,为了与cin的>>区分开来。
以一种情况为例:如果把stack存入到vector中,是可以的,但是当stack不够要resize的时候就会出错,原因是:出现了浅拷贝!resize()扩展数组内存空间的函数中,把原数组的元素复制到新数组,如果复制的是类,并且类中使用了堆区内存,就存在浅拷贝的问题。Stack类成员变量items是指针,使用了堆区内存,要用深拷贝,也就是说,对于Stack这种类,一定要重写拷贝构造函数和赋值函数。代码中用的赋值函数,那么就要为Stack类重写赋值函数,实现深拷贝。
需要对Stack类和Vector类的赋值函数进行重写,实现深拷贝:
// 用模板类实现一个栈
#include<iostream>
#include<string.h>
using namespace std;
// 类模板
template <class DataType>
class Stack
{
private:
DataType *items;
int stacksize;
int top;
public:
Stack(int stacksize = 3):stacksize(stacksize),top(0)
{
items = new DataType[stacksize];
}
~Stack()
{
delete []items; items = nullptr;
}
// 重写赋值函数,实现深拷贝,解决不能嵌套调用的问题
Stack& operator=(const Stack& ss)
{
stacksize = ss.stacksize; top = ss.top;
DataType* tmp = new DataType[stacksize];
for(int ii=0;ii<stacksize;ii++) tmp[ii] = ss.items[ii];
delete []items;
items = tmp;
tmp = nullptr;
return *this;
}
bool isempty()
{
return top == 0;
}
bool IsFull()
{
return top == stacksize;
}
bool push(const DataType& val)
{
if(IsFull()) {cout<<"栈已满"<<endl; return false;}
items[top] = val;
top++;
return true;
}
bool pop(DataType& elem)
{
if(isempty()) {cout<<"栈已空"<<endl; return false;}
top--;
elem = items[top];
return true;
}
};
template <class T>
class Vector
{
private:
T *items; // 数组元素
int len; // 数组元素的个数。
public:
Vector(int size = 2):len(size)
{
items = new T[len];
}
~Vector()
{
delete []items;items = nullptr;
}
// 重写赋值函数,实现深拷贝,解决不能嵌套调用的问题
Vector& operator=(const Vector& vv)
{
this->len = vv.len;
delete[] items;
items = new T[vv.len];
for(int ii=0;ii<this->len;ii++) items[ii] = vv.items[ii];
return *this;
}
bool resize(int size)
{
if(this->len>=size) return false;
T *tmp = new T[size];
for(int ii=0;ii<this->len;ii++) tmp[ii]=items[ii];
delete []items;
items = tmp;
this->len = size;
return true;
}
int size() const { return len; } // 获取数组长度。
T& operator[](int index) // 重载操作符[],可以修改数组中的元素。
{
if(index>=this->len) resize(index+1);
return items[index];
}
const T& operator[](int index) const // 重载操作符[],不能修改数组中的元
{
return items[index];
}
};
int main()
{
// Vector容器的大小缺省值是2,Stack容器的大小缺省值是3。
// 创建Vector容器,容器中的元素用Stack<string>。
Vector< Stack<string> > vs; // C++11之前,>>之间要加空格。
// 手工的往容器中插入数据。
vs[0].push("西施1"); vs[0].push("西施2"); vs[0].push("西施3"); // vs容器中的第0个栈。
vs[1].push("西瓜1"); vs[1].push("西瓜2"); vs[1].push("西瓜3"); // vs容器中的第1个栈。
vs[2].push("冰冰"); vs[2].push("幂幂"); // vs容器中的第2个栈。
// 用嵌套的循环,把vs容器中的数据显示出来。
for (int ii = 0; ii < vs.size(); ii++) // 遍历Vector容器。
{
while (vs[ii].isempty() == false) // 遍历Stack容器。
{
string item; vs[ii].pop(item); cout << "item = " << item << endl;
}
}
// 创建Stack容器,容器中的元素用Vector<string>。
Stack<Vector<string>> sv;
Vector<string> tmp; // 栈的元素,临时Vector<string>容器。
// 第一个入栈的元素。
tmp[0] = "西施1"; tmp[1] = "西施2"; sv.push(tmp);
// 第二个入栈的元素。
tmp[0] = "西瓜1"; tmp[1] = "西瓜2"; sv.push(tmp);
// 第三个入栈的元素。
tmp[0] = "冰冰1"; tmp[1] = "冰冰2"; tmp[2] = "冰冰3"; tmp[3] = "冰冰4"; sv.push(tmp);
// 用嵌套的循环,把sv容器中的数据显示出来。
while (sv.isempty() == false)
{
sv.pop(tmp); // 出栈一个元素,放在临时容器中。
for (int ii = 0; ii < tmp.size(); ii++) // 遍历临时Vector<string>容器,显示容器中每个元素的值。
cout << " vs[" << ii << "] = " << tmp[ii] << endl;
}
// 创建Vector容器,容器中的元素用Vector<string>。
Vector<Vector<string>> vv; // 递归使用模板类。
vv[0][0] = "西施1"; vv[0][1] = "西施2"; vv[0][2] = "西施3";
vv[1][0] = "西瓜1"; vv[1][1] = "西瓜2";
vv[2][0] = "冰冰1"; vv[2][1] = "冰冰2"; vv[2][2] = "冰冰3"; vv[2][3] = "冰冰4";
// 用嵌套的循环,把vv容器中的数据显示出来。
for (int ii = 0; ii < vv.size(); ii++)
{
for (int jj = 0; jj < vv[ii].size(); jj++)
// cout << " vv[" << ii << "][" << jj << "] = " << vv[ii][jj] << endl;
cout << vv[ii][jj] << " ";
cout << endl;
}
return 0;
}
标签:tmp,int,items,ii,嵌套,vv,拷贝,模板
From: https://blog.csdn.net/weixin_56520780/article/details/143232901