普通指针的不足,new和new[] 需要delete和delete[]
- 忘了
- 不清楚什么时候释放,比如多线程的共享一个对象时
普通指针的释放:
- 类内的指针,在析构函数中释放
- new 出来的类,也需要delete后才会调用析构函数
智能指针的设计思路
- 智能指针是类模板,在栈上创建智能指针对象。
- 把普通指针交给智能指针对象。
- 智能指针对象过期时,调用智能指针的析构函数释放普通指针的内存
auto_ptr已弃用,unique_ptr、shared ptr 和 weak ptr是C++11标准的
unique_ptr
unique_ptr
独享指向的对象,即只有一个 unique_ptr
指向一个同一个对象
模板类
通用类的描述,使用任意类型(泛型)来描述类的定义
template <class T1, class T2=默认类型,......> //数据类型
class 类模板名
{
类的定义;
}
template <class T1, class T2=int> //数据类型
class AA
{
public:
T1 m_a; //通用类型用于成员变量
T2 m_b;
AA() {}
//通用类型用于成员函数的参数
AA(T1 a, T2 b) :m_a(a), m_b(b) {}
//通用类型用于成员参数的返回值
T1 geta()
{
T1 a = 1; //通用类型用于成员函数的代码中
return m_a + a;
}
T1 getb()
{
T1 a = 1; //通用类型用于成员函数的代码中
return m_b + a;
}
};
int main()
{
AA<int, double> a;//模板类创建对象a
a.m_a = 20;a.m_b = 30;
cout << "a.geta()=" << a.geta() << endl;
cout << "a.getb()=" << a.getb() << endl;
}
注意:
1)在创建对象的时候,必须指明具体的数据类型
2)使用类模板时,数据类型必须适应类模板中的代码
3)类模板可以为通用参数指定缺省的数据类型
4)类的成员函数可以在类外实现
template <class T1, class T2> //数据类型
class AA
{
public:
T1 m_a; //通用类型用于成员变量
T2 m_b;
AA() {}
//通用类型用于成员函数的参数
AA(T1 a, T2 b) :m_a(a), m_b(b) {}
//通用类型用于成员参数的返回值
T1 geta()
{
T1 a = 1; //通用类型用于成员函数的代码中
return m_a + a;
}
T1 getb();
};
template <class T1, class T2>
T1 AA<T1,T2>::getb()
{
T1 a = 1; //通用类型用于成员函数的代码中
return m_b + a;
}
5)可以用 new 创建模板对象
int main()
{
//AA<int, double> a;//模板类创建对象a
//a.m_a = 20;a.m_b = 30;
//cout << "a.geta()=" << a.geta() << endl;
//cout << "a.getb()=" << a.getb() << endl;
AA<int, double> *a = new AA<int, double>(20,30);
cout << "a.geta()=" << a->geta() << endl;
cout << "a.getb()=" << a->getb() << endl;
}
6)用模板类创建的对象,任何成员函数只要不使用,就不会创建
template <class T1, class T2=int> //数据类型
class AA
{
public:
T1 m_a;
T2 m_b;
AA() {m_a.aaaanbbbbb();} //肯定会出错的代码
AA(T1 a, T2 b) :m_a(a), m_b(b) {}
};
int main()
{
AA<int, double> *a ; //不会报错
}
模板类示例-栈
模板类最常用的就是作为容器类
class Stack
{
private:
int* items; //栈数组
int stacksize; //栈实际的大小
int top; //栈顶指针 0 代表没有
public:
Stack(int size) :stacksize(size), top(0) { //分配栈数组内存 栈顶指针初始化为0
items = new int[stacksize]; //申请的数组首地址给指针
}
~Stack()
{
delete []items;
items = nullptr;
}
//const 常量成员函数 不会修改成员变量
bool isempty()const { //判断栈是否已空
return top == 0;
}
bool isfull()const { //判断栈是否已满
return top == stacksize;
}
bool push(const int& item) { //元素入栈
if (top < stacksize) { items[top++] = item;return true; } //先赋值,再移动top
return false;
}
bool pop(int& item){ //元素出栈
if (top > 0) { item = items[--top];return true; }
return false;
}
int getTop() { return top; }
//item = items[top]; // 先访问栈顶元素
//--top; // 然后将栈顶指针减1
};
int main()
{
Stack ss(5);
ss.push(1);
ss.push(2);
ss.push(3);
ss.push(4);
ss.push(5);
cout << "top=" << ss.getTop() << endl; //5
int item;
while (ss.isempty() == false) {
ss.pop(item);
cout << "item=" << item << endl;
}
}
如果不用模板类,则使用typedef int DataType
实现泛用
typedef int DataType;
class Stack
{
private:
DataType* items; //栈数组
int stacksize; //栈实际的大小
int top; //栈顶指针 0 代表没有
public:
Stack(int size) :stacksize(size), top(0) { //分配栈数组内存 栈顶指针初始化为0
items = new DataType[stacksize]; //申请的数组首地址给指针
}
~Stack()
{
delete []items;
items = nullptr;
}
//const 常量成员函数 不会修改成员变量
bool isempty()const { //判断栈是否已空
return top == 0;
}
bool isfull()const { //判断栈是否已满
return top == stacksize;
}
bool push(const DataType& item) { //元素入栈
if (top < stacksize) { items[top++] = item;return true; } //先赋值,再移动top
return false;
}
bool pop(int& item){ //元素出栈
if (top > 0) { item = items[--top];return true; }
return false;
}
int getTop() { return top; }
//item = items[top]; // 先访问栈顶元素
//--top; // 然后将栈顶指针减1
};
int main()
{
Stack ss(5);
ss.push(1);
ss.push(2);
ss.push(3);
ss.push(4);
ss.push(5);
cout << "top=" << ss.getTop() << endl; //5
DataType item;
while (ss.isempty() == false) {
ss.pop(item);
cout << "item=" << item << endl;
}
}
使用模板类
//typedef int DataType;
template<class DataType>
class Stack
{
private:
DataType* items; //栈数组
int stacksize; //栈实际的大小
int top; //栈顶指针 0 代表没有
public:
Stack(int size) :stacksize(size), top(0) { //分配栈数组内存 栈顶指针初始化为0
items = new DataType[stacksize]; //申请的数组首地址给指针
}
~Stack()
{
delete []items;
items = nullptr;
}
//const 常量成员函数 不会修改成员变量
bool isempty()const { //判断栈是否已空
return top == 0;
}
bool isfull()const { //判断栈是否已满
return top == stacksize;
}
bool push(const DataType& item) { //元素入栈
if (top < stacksize) { items[top++] = item;return true; } //先赋值,再移动top
return false;
}
bool pop(int& item){ //元素出栈
if (top > 0) { item = items[--top];return true; }
return false;
}
int getTop() { return top; }
//item = items[top]; // 先访问栈顶元素
//--top; // 然后将栈顶指针减1
};
int main()
{
Stack<int> ss(5);
ss.push(1);
ss.push(2);
ss.push(3);
ss.push(4);
ss.push(5);
cout << "top=" << ss.getTop() << endl; //5
int item;
while (ss.isempty() == false) {
ss.pop(item);
cout << "item=" << item << endl;
}
}
模板类示例-数组
- 定长数组:array 容器
- 可变数组:vector 容器