笔记 C++智能指针 auto_ptr 及其自己简单地实现 auto_ptr 和 shared_ptr

本文探讨了C++中传统指针可能导致的内存泄漏问题,然后介绍了C++98的`auto_ptr`如何自动管理内存。接着,展示了如何自定义一个简单的智能指针类来模仿`auto_ptr`的功能。最后,给出了C++11的`shared_ptr`的简单实现,强调了其引用计数和资源管理的特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 传统指针

  • 需要时时刻刻记住 new 了后要 delelte
#include <iostream>

using namespace std;

template <typename T>
class complex {
private:
	T re;
	T im;

public:
	complex(const T r, const T i): re(r), im(i) {
		cout << "init complex" << endl;
	}

	const void print() {
		cout << re << " + " << im << "i" << endl;
	}

	~complex() {
		cout << "free complex" << endl;
	}
};

int main() {

	complex<int>* p = new complex<int>(10, 10);
	p->print();
	delete p;

	return 0;
}

  • 结果: 容易泄露内存,比如 忘记写 或者 出现异常
#include <iostream>

using namespace std;

template <typename T>
class complex {
private:
	T re;
	T im;

public:
	complex(const T r, const T i): re(r), im(i) {
		cout << "init complex" << endl;
	}

	const void print() {
		cout << re << " + " << im << "i" << endl;
	}

	~complex() {
		cout << "free complex" << endl;
	}
};


void test() {
	// 运行时出错
}

int main() {

	complex<int>* p = new complex<int>(10, 10);
	p->print();

	test();		// 运行时出错

	delete p;	// delete 不执行

	return 0;
}

2. C++ 98 的智能指针 auto_ptr (缺点:不能用于数组)

  • 开辟一个放在栈空间的指针,在作用域完后释放 new 的对象,不需要使用 delete 释放对象
#include <iostream>

using namespace std;

template <typename T>
class complex {
private:
	T re;
	T im;

public:
	complex(const T r, const T i): re(r), im(i) {
		cout << "init complex" << endl;
	}

	const void print() {
		cout << re << " + " << im << "i" << endl;
	}

	~complex() {
		cout << "free complex" << endl;
	}
};


int main() {

	cout << "start" << endl;
	{
	auto_ptr<complex<double>> p(new complex<double>(1.0, 1.0));
	p->print();
	}
	cout << "end" << endl;

	return 0;
}

在这里插入图片描述

3. 自己实现一个简单的 C++ 98 的智能指针

#include <iostream>

using namespace std;

template <typename T>
class complex {
private:
	T re;
	T im;

public:
	complex(const T r, const T i): re(r), im(i) {
		cout << "init complex" << endl;
	}

	const void print() {
		cout << re << " + " << im << "i" << endl;
	}

	~complex() {
		cout << "free complex" << endl;
	}
};



template <typename T>
class SmartPointer {
private:
	T* sPointer;

public:
	SmartPointer(T *p): sPointer(p){}

	~SmartPointer() {
		if (sPointer == nullptr) { return; }
		delete sPointer;
	}
	// 关键:重定义运算符 ->, 使对象能调用指针里的方法
	T* operator -> () {
		return sPointer;
	}

};


int main() {


	// 系统的智能指针
	cout << "system_smart_pointer_start" << endl;
	{
	auto_ptr<complex<double>> p(new complex<double>(1.0, 1.0));
	p->print();
	}
	cout << "system_smart_pointer_end" << endl;

	// 自定义的智能指针
	cout << "defined_ourselves_start" << endl;
	{
		SmartPointer<complex<double>> p(new complex<double>(1.0, 1.0));
		p->print();
	}
	cout << "defined_ourselves_end" << endl;

	return 0;
}

在这里插入图片描述


  • 2021.06.18 更新

4. 简单实现 C++11shared_ptr

#include <iostream>
#include <memory>
#include <cassert>


template <typename T>
class SmartPoint {
private:
    T* _ptr;
    size_t* _count;

public:
    SmartPoint(T* ptr = nullptr) : _ptr(ptr) {
        if (ptr) {
            _count = new size_t(1);
        }
        else {
            _count = new size_t(0);
        }
    }

    ~SmartPoint() {
        // 析构一次,计数减 1.
        (*this->count)--;

        // 如果计数为 0, delete 指针
        if (*this->count == 0) {
            delete this->_ptr;
            delete this->_count;
        }
    }

    // 拷贝构造,计数 +1
    SmartPoint(const SmartPoint& ptr) {
        if (this != &ptr) {
            this->_ptr = ptr._ptr;
            this->_count = ptr._count;
            (*this->_count)++;
        }
    }

    SmartPoint& operator=(const SmartPoint& ptr) {
        if (this->_ptr == ptr._ptr) {
            return *this;
        }
        // 将当前的 ptr 指向的原来的空间的计数 -1
        if (this->_ptr) {
            (*this->_count)--;
            if (this->_count == 0) {
                delete this->_ptr;
                delete this->_count;
            } 
        }

        this->_ptr = ptr._ptr;
        this->_count = ptr._count;
        // 此时 ptr 指向了新赋值的空间,该空间的计数 +1
        (*this->_count)++;
        return *this;
    }

    // 重载 *
    T& operator*() {
        assert(this->_ptr == nullptr);
        return *(this->_ptr);
    }

    // 重载 ->
    T* operator->() {
        assert(this->_ptr == nullptr);
        return this->_ptr;
    }

    // 计数
    size_t use_count(){
        return this->_count;
    }
};




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值