智能指针
- 使用new在堆区动态分配内存时,需要delete释放否则会导致内存泄漏,所以采用智能指针即将动态创建时的指针传入,然后通过智能指针的析构函数delete即可释放资源,通过RAII技术确保内存被正确释放,有效防止内存泄漏。
- 智能指针实际上是类对象,重载了类如->、*等指针常用的运算符,只是表现形式像指针
- C++11摒弃auto_ptr并新增提供了三种智能指针unique_ptr、shared_ptr、weak_ptr, 其作用和使用详见 C++11新特性 第4点
- 示例-手动实现简单的智能指针类来管理动态创建的对象
#include<iostream>
#include<string>
using namespace std;//类模板-智能指针类
template<typename CLASSNAME>
class SmartPoint {
public:SmartPoint() {this->m_ptr = nullptr;}SmartPoint(CLASSNAME *ptr) {this->m_ptr = ptr;}// 禁止拷贝构造和拷贝赋值SmartPoint(const SmartPoint&) = delete;SmartPoint& operator=(const SmartPoint&) = delete;//RAII机制释放资源~SmartPoint() {if (this->m_ptr != nullptr) {cout<<"use ~SmartPoint()"<<endl;delete this->m_ptr;this->m_ptr = nullptr;}}// 移动构造函数SmartPoint(SmartPoint&& other) noexcept : m_ptr(other.m_ptr) {//初始化列表不允许用this,直接使用成员变量即可other.m_ptr = nullptr; // 确保原对象不再拥有资源}// 移动赋值运算符SmartPoint& operator=(SmartPoint&& other) noexcept {if (this != &other) {delete this->m_ptr; // 释放当前资源this->m_ptr = other.m_ptr;other.m_ptr = nullptr;}return *this;}explicit operator bool() const { return this->m_ptr != nullptr; }CLASSNAME* operator->() const{//重载->if (!this->m_ptr) {throw std::runtime_error("Attempt to dereference null pointer");}return this->m_ptr;}CLASSNAME& operator*() const{//重载*if (!this->m_ptr) {throw std::runtime_error("Attempt to dereference null pointer");}return *(this->m_ptr);}CLASSNAME* get() const { return this->m_ptr; } CLASSNAME* release() noexcept{ CLASSNAME* ptr = this->m_ptr;this->m_ptr = nullptr;return ptr;}const CLASSNAME* release() const noexcept = delete; // 禁止const对象releasevoid set(CLASSNAME* ptr) {if (this->m_ptr != ptr) {CLASSNAME* old = this->m_ptr;this->m_ptr = ptr; // 先设置新指针delete old; // 再删除旧指针}}private:CLASSNAME* m_ptr;//内部维护指针
};//父类
template<typename NAMETYPE,typename AGETYPE>
class Person {
public:Person(NAMETYPE name, AGETYPE age) {this->m_Name = name;this->m_Age = age;}virtual ~Person() = default;//确保子类资源释放virtual void show() {cout << this->m_Age<<"--" << this->m_Name << endl;}NAMETYPE m_Name;AGETYPE m_Age;
};//子类
template<typename NAMETYPE, typename AGETYPE>
class Son :public Person<NAMETYPE, AGETYPE> {
public:Son(NAMETYPE name, AGETYPE age) :Person<NAMETYPE,AGETYPE>(name, age) {//调用父类有参构造}~Son(){cout<<"use ~Son()"<<endl;}void show() override {//确保重写cout << this->m_Name<<"--" << this->m_Age << endl;}
};int main() {//通过有参构造使用Person<string,int>* p1 = new Person<string, int>("Tom", 22);SmartPoint<Person<string,int>> sp1(p1);sp1->show();Person<string, int>* p2 = new Son<string, int>("JERRY", 22);SmartPoint<Person<string, int>> sp2(p2);sp2->show();//调用get、set使用SmartPoint<Person<string, int>> sp3;Person<string, int>* p3 = new Son<string, int>("Tom-Mom", 44);sp3.set(p3);sp3.get()->show();//测试releaseauto rawPtr = sp3.release();//模仿移动语义rawPtr->show();delete rawPtr;// 测试移动语义-RAII机制仅释放两次SmartPoint<Person<string, int>> sp4 = std::move(sp1);if (!sp1) cout << "sp1 is empty after move"<<endl;sp4->show();return 0;
}