一、C++实现shared_ptr
实现要点
- 模板类,对实际指针数据类型T*进行封装,有效防止内存泄露,类实例在离开作用域后自动析构
- 共享引用次数(指针类型),在构造函数中需要new一块内存,在清零的情况下delete
- 重载拷贝构造函数、赋值函数,count加1
- 重载解引用operator*和取成员符号operator->
- 重载析构函数,引用次数减1,并判断是否delete
#include <iostream>
#include <memory>
template <typename T>
class shared_ptr {
private:
int *count_;
T *ptr_;
public:
shared_ptr(T *p) : count_(new int (1)), ptr_(p) {} // 构造函数
shared_ptr(shared_ptr<T>& other) : count_(&(++*other.count_)), ptr_(other.ptr_) {} // 拷贝构造函数
T* operator->() { return ptr_; } // 重载->
T& operator*() { return *ptr_; } // 重载*
shared_ptr<T>& operator=(shared_ptr<T>& other) { // 赋值函数
++*other.count_;
if (this->ptr_ && 0 == --*this->count_) {
delete count_;
delete ptr_;
}
this->ptr_ = other.ptr_;
this->count_ = other.count_;
return *this;
}
~shared_ptr() { // 析构函数
if (--*count_ == 0) {
delete count_;
delete ptr_;
}
}
int use_count() { return *count_; }
};
int main() {
std::cout << "hello lch!" << std::endl;
shared_ptr<int> temp1(new int(100));
shared_ptr<int> temp2(temp1);
std::cout << temp1.use_count() << std::endl;
std::cout << temp2.use_count() << std::endl;
std::cout << *temp1 << std::endl;
std::cout << *temp2 << std::endl;
std::shared_ptr<int> temp3(new int (200));
std::cout << temp3.use_count() << std::endl;
std::cout << *temp3 << std::endl;
std::cout << "end lch!" << std::endl;
return 0;
}
二、C++实现unique_ptr
实现要点
- 模板类,对实际指针数据类型T*进行封装,有效防止内存泄露,类实例在离开作用域后自动析构
- 禁用拷贝构造和赋值函数,独占指针所有权
- 实现移动构造函数和移动赋值函数(右值只用),支持所有权转移(std::move)
- reset和release实现
- 重载解引用operator*和取成员符号operator->
#include <iostream>
#include <memory>
#include <iostream>
template <typename T>
class unique_ptr {
public:
constexpr unique_ptr() noexcept : ptr_(nullptr) {}
constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() {} // typedef decltype(nullptr) nullptr_t;
explicit unique_ptr(T *ptr) noexcept : ptr_(ptr) {}
~unique_ptr() noexcept { delete ptr_; }
unique_ptr(const unique_ptr &) = delete; // 禁用拷贝构造函数
unique_ptr& operator=(const unique_ptr &) = delete; // 禁用赋值函数
unique_ptr(unique_ptr &&other) noexcept : ptr_(other.release()) {}
unique_ptr &operator=(unique_ptr &&other) noexcept {
this->reset(other.release());
return *this;
}
unique_ptr &operator=(nullptr_t) {
this->reset();
return *this;
}
T& operator*() const noexcept { return *ptr_; }
T* operator->() const noexcept { return ptr_; }
T* release() noexcept { // return std::exchange(ptr_, nullptr); // C++14用法
T* temp = ptr_;
ptr_ = nullptr;
return temp;
}
void reset(T *ptr) noexcept { // return std::exchange(ptr_, ptr); // C++14用法
ptr_ = ptr;
}
T* get() const noexcept { return ptr_; }
void swap(unique_ptr &other) noexcept { std::swap(ptr_, other.ptr_); };
operator bool() const noexcept { return static_cast<bool>(ptr_); }
void test_print() { std::cout << "test number is " << ++num << std::endl; }
private:
T *ptr_;
static int num;
};
template <typename T>
int unique_ptr<T>::num = 0;
template <typename T, typename... Args>
auto make_unique(Args &&... args) {
return unique_ptr<T>(new T(std::forward(args)...));
}
int main() {
std::cout << "hello lch !!!" << std::endl;
unique_ptr<int> ptr(new int (100));
std::cout << &ptr << std::endl;
std::cout << *ptr << std::endl;
std::cout << bool(ptr) << std::endl;
(void)ptr.test_print();
unique_ptr<int> ptr1;
std::cout << bool(ptr1) << std::endl;
ptr1 = make_unique<int>();
*ptr1 = 200;
std::cout << &ptr1 << std::endl;
std::cout << *ptr1 << std::endl;
std::cout << bool(ptr1) << std::endl;
(void)ptr1.test_print();
unique_ptr<int> *ptr2 = new unique_ptr<int>();
std::cout << &ptr2 << std::endl;
std::cout << *ptr2 << std::endl;
(void)ptr2->test_print();
std::cout << "end lch !!!" << std::endl;
return 0;
}