C++ 智能指针详解:std::unique_ptr、std::shared_ptr 和 std::weak_ptr

在 C++ 中,智能指针是一种管理动态内存的工具,能够自动释放内存,避免内存泄漏。C++ 标准库提供了几种智能指针,主要包括 std::unique_ptr、std::shared_ptr 和 std::weak_ptr。以下是它们的详细介绍:

1. std::unique_ptr
std::unique_ptr 是一种独占所有权的智能指针。它确保同一时间只有一个 unique_ptr 可以指向某个对象,当 unique_ptr 被销毁时,它所管理的对象也会被自动释放。

特点:
独占所有权:不能复制,只能移动(通过 std::move)。

轻量级:几乎没有额外的开销。

适用于单一所有权的场景。

示例:

#include <memory>
#include <iostream>

int main() {
    int a = 1;
	char b = 'a';
	//自动创建
	std::unique_ptr<int> ptr1 = std::make_unique<int>(10);
	std::unique_ptr<int[]> ptr2 = std::make_unique<int[]>(10);
	std::unique_ptr<int*> ptr3 = std::make_unique<int*>(&a);
	std::unique_ptr<char> ptr4 = std::make_unique<char>('a');
	std::unique_ptr<char[]> ptr5 = std::make_unique<char[]>(10);
	std::unique_ptr<char*> ptr6 = std::make_unique<char*>(&b);

	//手动创建
	std::unique_ptr<char[], std::default_delete<char[]>> ptr8(new char[10]());

	//std::unique_ptr<int> ptr7 = ptr1; // 错误:不能复制
	std::unique_ptr<int> ptr7 = std::move(ptr1);
	if (!ptr1) {
		std::cout << "ptr1 is now null" << std::endl;
	}

    return 0; //自动释放内存
}

主要成员函数:
get()

功能:返回指向托管对象的原始指针。

使用:用于需要原始指针的场景,例如与 C 风格 API 交互。

示例:

std::unique_ptr<int> ptr = std::make_unique<int>(42);
int* raw_ptr = ptr.get(); // 获取原始指针

reset()

功能:释放当前托管的对象(如果有),并可选地接管一个新的对象。

使用:用于显式释放资源或替换托管对象。

示例:

ptr.reset(); // 释放当前对象
ptr.reset(new int(100)); // 释放当前对象并接管新对象

release()

功能:释放对托管对象的所有权,返回原始指针。

使用:用于将所有权转移给其他代码。

示例:

int* raw_ptr = ptr.release(); // 释放所有权,ptr 变为空

operator* 和 operator->

功能:访问托管对象。

使用:用于访问对象的成员或解引用。

示例:

std::unique_ptr<std::string> ptr = std::make_unique<std::string>("Hello");
std::cout << *ptr << std::endl; // 解引用
std::cout << ptr->size() << std::endl; // 访问成员函数

get_deleter()

简介:用于获取智能指针关联的删除器(deleter)。删除器是一个可调用对象(如函数指针、函数对象或 Lambda 表达式),用于在智能指针释放资源时执行自定义的清理操作。默认情况下,智能指针使用 delete 或 delete[] 来释放资源,但通过自定义删除器,可以实现更复杂的资源管理逻辑(例如关闭文件、释放锁、调用特定 API 等)。

函数签名:
deleter_type& get_deleter() noexcept;
const deleter_type& get_deleter() const noexcept;

功能:
返回 unique_ptr 的删除器的引用。

如果 unique_ptr 没有自定义删除器,则返回默认删除器。

使用场景:
1.需要访问或修改 unique_ptr 的删除器时。

2.调试或检查删除器的状态。

示例1:

#include <iostream>
#include <memory>

int main() {
    // 手动分配内存
    char* raw_ptr = new char[10];

    // 使用 std::unique_ptr<T[]> 接管内存
    std::unique_ptr<char[]> ptr(raw_ptr);
	//std::unique_ptr<char[], std::default_delete<char[]>> ptr(new char[10]());	//等效于

    // 使用 ptr 访问数组
    ptr[0] = 'a';
    ptr[1] = 'b';
    std::cout << ptr[0] << ", " << ptr[1] << std::endl;

    // 内存会在 ptr 销毁时自动释放
    return 0;
}

示例2:

#include <iostream>
#include <memory>

int main() {
    // 手动分配内存
    char* raw_ptr = new char[10];

    // 使用自定义删除器接管内存
    std::unique_ptr<char, void(*)(char*)> ptr(raw_ptr, [](char* p) {
        delete[] p; // 确保调用 delete[]
        std::cout << "Memory released" << std::endl;
    });

    // 使用 ptr 访问数组
    ptr.get()[0] = 'a';
    ptr.get()[1] = 'b';
    std::cout << ptr.get()[0] << ", " << ptr.get()[1] << std::endl;

    // 内存会在 ptr 销毁时自动释放
    return 0;
}

示例3:

#include <iostream>
#include <memory>

// 自定义删除器
struct FileDeleter {
    void operator()(FILE* file) const {
        if (file) {
            std::cout << "Closing file" << std::endl;
            fclose(file);
        }
    }
};

int main() {
    // 使用自定义删除器创建 unique_ptr
    std::unique_ptr<FILE, FileDeleter> filePtr(fopen("test.txt", "w"));

    // 获取删除器
    FileDeleter& deleter = filePtr.get_deleter();
    std::cout << "Deleter obtained" << std::endl;

    // 文件会在 unique_ptr 销毁时自动关闭
    return 0;
}

2. std::shared_ptr
std::shared_ptr 是一种共享所有权的智能指针。它通过引用计数来管理资源,当最后一个 shared_ptr 被销毁时,资源才会被释放。

特点:
共享所有权:多个 shared_ptr 可以指向同一个对象。

引用计数:内部维护一个计数器,记录有多少个 shared_ptr 指向同一对象。

适用于共享所有权的场景。

示例:

#include <memory>
#include <iostream>

int main() {
    std::shared_ptr<int> ptr1 = std::make_shared<int>(20); // 创建一个 shared_ptr
    std::shared_ptr<int> ptr2 = ptr1; // 复制,引用计数增加

    std::cout << *ptr1 << " " << *ptr2 << std::endl; // 输出 20 20
    std::cout << "Use count: " << ptr1.use_count() << std::endl; // 输出 2

    ptr1.reset(); // ptr1 不再指向对象,引用计数减少
    std::cout << "Use count after reset: " << ptr2.use_count() << std::endl; // 输出 1

    return 0; // ptr2 自动释放内存
}

主要成员函数:
get()

功能:返回指向托管对象的原始指针。

使用:与 unique_ptr::get() 类似。

示例:

std::shared_ptr<int> ptr = std::make_shared<int>(42);
int* raw_ptr = ptr.get(); // 获取原始指针

reset()

功能:释放当前托管的对象(如果有),并可选地接管一个新的对象。

使用:与 unique_ptr::reset() 类似。

示例:

ptr.reset(); // 释放当前对象
ptr.reset(new int(100)); // 释放当前对象并接管新对象

use_count()

功能:返回当前共享对象的引用计数。

使用:用于调试或检查共享状态。

示例:

std::shared_ptr<int> ptr1 = std::make_shared<int>(42);
std::shared_ptr<int> ptr2 = ptr1;
std::cout << ptr1.use_count() << std::endl; // 输出 2

operator* 和 operator->

功能:访问托管对象。

使用:与 unique_ptr 相同。

示例:

std::shared_ptr<std::string> ptr = std::make_shared<std::string>("Hello");
std::cout << *ptr << std::endl; // 解引用
std::cout << ptr->size() << std::endl; // 访问成员函数

swap()

功能:交换两个 shared_ptr 的内容。

使用:用于交换托管对象。

示例:

std::shared_ptr<int> ptr1 = std::make_shared<int>(42);
std::shared_ptr<int> ptr2 = std::make_shared<int>(100);
ptr1.swap(ptr2); // 交换 ptr1 和 ptr2 的内容

std::shared_ptr::get_deleter函数

简介: std::shared_ptr 的 get_deleter 函数用于获取其关联的删除器。

函数签名:
template <typename Deleter>
Deleter* get_deleter() const noexcept;

功能:
1.返回指向 shared_ptr 删除器的指针。

2.如果 shared_ptr 没有指定类型的删除器,则返回 nullptr。

使用场景:
需要检查 shared_ptr 是否使用了特定类型的删除器时。

调试或检查删除器的状态。

示例1:

#include <iostream>
#include <memory>

// 自定义删除器
struct FileDeleter {
    void operator()(FILE* file) const {
        if (file) {
            std::cout << "Closing file" << std::endl;
            fclose(file);
        }
    }
};

int main() {
    // 使用自定义删除器创建 shared_ptr
    std::shared_ptr<FILE> filePtr(fopen("test.txt", "w"), FileDeleter());

    // 获取删除器
    auto* deleter = std::get_deleter<FileDeleter>(filePtr);
    if (deleter) {
        std::cout << "Custom deleter found" << std::endl;
    } else {
        std::cout << "No custom deleter" << std::endl;
    }

    // 文件会在 shared_ptr 销毁时自动关闭
    return 0;
}

示例2:

#include <iostream>
#include <memory>

int main() {
    // 手动分配内存
    char* raw_ptr = new char[10];

    // 定义自定义删除器
    auto deleter = [](char* p) {
        delete[] p; // 调用 delete[] 释放数组
        std::cout << "Custom deleter: Memory released" << std::endl;
    };

    // 使用 std::shared_ptr 接管内存,并指定自定义删除器
    std::shared_ptr<char> shared_ptr(raw_ptr, deleter);

    // 使用 std::weak_ptr 观察 shared_ptr
    std::weak_ptr<char> weak_ptr(shared_ptr);

    // 使用 weak_ptr 访问数组
    if (auto temp = weak_ptr.lock()) {
        temp.get()[0] = 'a';
        temp.get()[1] = 'b';
        std::cout << temp.get()[0] << ", " << temp.get()[1] << std::endl;
    }

    // 内存会在 shared_ptr 销毁时自动释放,调用自定义删除器
    return 0;
}

示例3:

#include <iostream>
#include <memory>
#include <cstdio>

int main() {
    // 打开文件
    FILE* file = fopen("test.txt", "w");

    // 定义自定义删除器
    auto deleter = [](FILE* f) {
        if (f) {
            fclose(f); // 关闭文件
            std::cout << "Custom deleter: File closed" << std::endl;
        }
    };

    // 使用 std::unique_ptr 接管文件句柄,并指定自定义删除器
    std::unique_ptr<FILE, decltype(deleter)> file_ptr(file, deleter);

    // 使用文件句柄
    if (file_ptr) {
        fprintf(file_ptr.get(), "Hello, World!");
    }

    // 文件会在 file_ptr 销毁时自动关闭
    return 0;
}

3. std::weak_ptr
std::weak_ptr是一种弱引用的智能指针,用于观察std::shared_ptr管理的资源,不会增加引用计数。它通常与 std::shared_ptr 配合使用,用于解决循环引用问题。

特点:
弱引用:不增加引用计数,不会阻止对象的销毁。

需要转换为 shared_ptr 才能访问对象。

适用于解决循环引用问题。

示例:

#include <memory>
#include <iostream>

int main() {
    std::shared_ptr<int> sharedPtr = std::make_shared<int>(30);
    std::weak_ptr<int> weakPtr = sharedPtr; // 创建一个 weak_ptr

    std::cout << "Use count: " << sharedPtr.use_count() << std::endl; // 输出 1

    if (auto lockedPtr = weakPtr.lock()) { // 转换为 shared_ptr
        std::cout << *lockedPtr << std::endl; // 输出 30
    } else {
        std::cout << "Object has been destroyed" << std::endl;
    }

    sharedPtr.reset(); // 释放对象
    if (weakPtr.expired()) {
        std::cout << "Object has been destroyed" << std::endl;
    }

    return 0;
}

主要成员函数:
构造函数
std::weak_ptr 可以通过 std::shared_ptr 或另一个 std::weak_ptr 构造。

函数签名:
weak_ptr() noexcept; // 默认构造函数,创建一个空的 weak_ptr
weak_ptr(const weak_ptr& other) noexcept; // 拷贝构造函数
weak_ptr(weak_ptr&& other) noexcept; // 移动构造函数
weak_ptr(const shared_ptr<T>& other) noexcept; // 从 shared_ptr 构造

示例:

#include <iostream>
#include <memory>

int main() {
    // 创建一个 shared_ptr
    std::shared_ptr<int> shared = std::make_shared<int>(42);

    // 从 shared_ptr 构造 weak_ptr
    std::weak_ptr<int> weak1(shared);

    // 从另一个 weak_ptr 构造 weak_ptr
    std::weak_ptr<int> weak2(weak1);

    // 默认构造一个空的 weak_ptr
    std::weak_ptr<int> weak3;

    return 0;
}

operator=
std::weak_ptr 支持拷贝赋值和移动赋值。

函数签名:
weak_ptr& operator=(const weak_ptr& other) noexcept; // 拷贝赋值
weak_ptr& operator=(weak_ptr&& other) noexcept; // 移动赋值
weak_ptr& operator=(const shared_ptr<T>& other) noexcept; // 从 shared_ptr 赋值

示例:

#include <iostream>
#include <memory>

int main() {
    // 创建一个 shared_ptr
    std::shared_ptr<int> shared = std::make_shared<int>(42);

    // 创建一个 weak_ptr
    std::weak_ptr<int> weak;

    // 从 shared_ptr 赋值
    weak = shared;

    // 从另一个 weak_ptr 赋值
    std::weak_ptr<int> weak2;
    weak2 = weak;

    return 0;
}

reset()
reset() 用于释放 std::weak_ptr 对资源的观察权,使其变为空指针。

函数签名:
void reset() noexcept;
示例:

#include <iostream>
#include <memory>

int main() {
    // 创建一个 shared_ptr
    std::shared_ptr<int> shared = std::make_shared<int>(42);

    // 创建一个 weak_ptr
    std::weak_ptr<int> weak(shared);

    // 释放 weak_ptr 的观察权
    weak.reset();

    // 检查 weak_ptr 是否为空
    if (weak.expired()) {
        std::cout << "weak_ptr is empty" << std::endl;
    }

    return 0;
}

swap()
swap() 用于交换两个 std::weak_ptr 的内容。

函数签名:
void swap(weak_ptr& other) noexcept;
示例:

#include <iostream>
#include <memory>

int main() {
    // 创建两个 shared_ptr
    std::shared_ptr<int> shared1 = std::make_shared<int>(42);
    std::shared_ptr<int> shared2 = std::make_shared<int>(100);

    // 创建两个 weak_ptr
    std::weak_ptr<int> weak1(shared1);
    std::weak_ptr<int> weak2(shared2);

    // 交换 weak1 和 weak2 的内容
    weak1.swap(weak2);

    return 0;
}

use_count()
use_count() 返回与 std::weak_ptr 关联的 std::shared_ptr 的引用计数。

函数签名:
long use_count() const noexcept;
示例:

#include <iostream>
#include <memory>

int main() {
    // 创建一个 shared_ptr
    std::shared_ptr<int> shared = std::make_shared<int>(42);

    // 创建一个 weak_ptr
    std::weak_ptr<int> weak(shared);

    // 获取引用计数
    std::cout << "use_count: " << weak.use_count() << std::endl; // 输出 1

    return 0;
}

expired()
expired() 用于检查与 std::weak_ptr 关联的 std::shared_ptr 是否已经释放资源。

函数签名:
bool expired() const noexcept;
示例:

#include <iostream>
#include <memory>

int main() {
    // 创建一个 shared_ptr
    std::shared_ptr<int> shared = std::make_shared<int>(42);

    // 创建一个 weak_ptr
    std::weak_ptr<int> weak(shared);

    // 检查资源是否已释放
    if (!weak.expired()) {
        std::cout << "Resource is still alive" << std::endl;
    }

    // 释放 shared_ptr
    shared.reset();

    // 再次检查资源是否已释放
    if (weak.expired()) {
        std::cout << "Resource has been released" << std::endl;
    }

    return 0;
}

lock()
lock() 用于获取一个与 std::weak_ptr 关联的 std::shared_ptr。如果资源已被释放,则返回一个空的 std::shared_ptr。

函数签名:
shared_ptr<T> lock() const noexcept;
示例:

#include <iostream>
#include <memory>

int main() {
    // 创建一个 shared_ptr
    std::shared_ptr<int> shared = std::make_shared<int>(42);

    // 创建一个 weak_ptr
    std::weak_ptr<int> weak(shared);

    // 使用 lock() 获取 shared_ptr
    if (auto temp = weak.lock()) {
        std::cout << "Resource value: " << *temp << std::endl;
    } else {
        std::cout << "Resource has been released" << std::endl;
    }

    // 释放 shared_ptr
    shared.reset();

    // 再次尝试获取 shared_ptr
    if (auto temp = weak.lock()) {
        std::cout << "Resource value: " << *temp << std::endl;
    } else {
        std::cout << "Resource has been released" << std::endl;
    }

    return 0;
}

owner_before()
owner_before() 用于比较两个 std::weak_ptr 的所有权顺序(通常用于实现自定义排序)。

函数签名:
template <typename U>
bool owner_before(const weak_ptr<U>& other) const noexcept;

template <typename U>
bool owner_before(const shared_ptr<U>& other) const noexcept;
示例:

#include <iostream>
#include <memory>

int main() {
    // 创建两个 shared_ptr
    std::shared_ptr<int> shared1 = std::make_shared<int>(42);
    std::shared_ptr<int> shared2 = std::make_shared<int>(100);

    // 创建两个 weak_ptr
    std::weak_ptr<int> weak1(shared1);
    std::weak_ptr<int> weak2(shared2);

    // 比较所有权顺序
    if (weak1.owner_before(weak2)) {
        std::cout << "weak1 is ordered before weak2" << std::endl;
    }

    return 0;
}

4. 对比总结

特性std::unique_ptrstd::shared_ptrstd::weak_ptr
所有权独占共享无所有权(弱引用)
引用计数无(不增加引用计数)
复制语义不可复制,只能移动可复制可复制
适用场景单一所有权共享所有权解决循环引用
性能开销较高(引用计数)

5. 使用建议
优先使用 std::unique_ptr,因为它更轻量且语义明确。

如果需要共享所有权,使用 std::shared_ptr。

如果存在循环引用问题,使用 std::weak_ptr 来打破循环。

通过合理使用智能指针,可以显著减少内存泄漏和资源管理错误。

6. 若指针设计初衷
在 C++ 中,循环引用(Circular Reference)是指两个或多个对象相互持有对方的 std::shared_ptr,导致它们的引用计数永远不会降为 0,从而造成内存泄漏。为了解决这个问题,可以使用 std::weak_ptr 来打破循环引用。

什么是循环引用?
循环引用通常发生在两个或多个对象相互持有对方的 std::shared_ptr 时。例如:

#include <memory>
#include <iostream>

class B; // 前向声明

class A {
public:
    std::shared_ptr<B> b_ptr;
    ~A() { std::cout << "A destroyed" << std::endl; }
};

class B {
public:
    std::shared_ptr<A> a_ptr;
    ~B() { std::cout << "B destroyed" << std::endl; }
};

int main() {
    auto a = std::make_shared<A>();
    auto b = std::make_shared<B>();

    a->b_ptr = b; // A 持有 B 的 shared_ptr
    b->a_ptr = a; // B 持有 A 的 shared_ptr

    // 此时引用计数:
    // a 的引用计数:2(main 中的 a 和 b->a_ptr)
    // b 的引用计数:2(main 中的 b 和 a->b_ptr)

    return 0; // a 和 b 的引用计数不会降为 0,导致内存泄漏
}

在上面的代码中:

A 对象持有 B 对象的 std::shared_ptr。

B 对象持有 A 对象的 std::shared_ptr。

当 main 函数结束时,a 和 b 的引用计数仍然为 1(因为互相持有对方的 shared_ptr),导致它们的内存无法被释放。

为什么使用 std::weak_ptr?
std::weak_ptr 是一种弱引用,它不会增加对象的引用计数。通过将其中一个 std::shared_ptr 替换为 std::weak_ptr,可以打破循环引用,从而避免内存泄漏。

修改后的代码:

#include <memory>
#include <iostream>

class B; // 前向声明

class A {
public:
    std::shared_ptr<B> b_ptr;
    ~A() { std::cout << "A destroyed" << std::endl; }
};

class B {
public:
    std::weak_ptr<A> a_ptr; // 使用 weak_ptr 代替 shared_ptr
    ~B() { std::cout << "B destroyed" << std::endl; }
};

int main() {
    auto a = std::make_shared<A>();
    auto b = std::make_shared<B>();

    a->b_ptr = b; // A 持有 B 的 shared_ptr
    b->a_ptr = a; // B 持有 A 的 weak_ptr

    // 此时引用计数:
    // a 的引用计数:1(只有 main 中的 a)
    // b 的引用计数:2(main 中的 b 和 a->b_ptr)

    return 0; // a 和 b 的引用计数会降为 0,内存被正确释放
}

std::weak_ptr 的工作原理
不增加引用计数:

std::weak_ptr 不会增加对象的引用计数,因此不会影响对象的生命周期。

当最后一个 std::shared_ptr 被销毁时,对象会被释放,即使有 std::weak_ptr 指向它。

需要转换为 std::shared_ptr 才能访问对象:

通过 lock() 方法,std::weak_ptr 可以转换为 std::shared_ptr,从而访问对象。

如果对象已经被释放,lock() 会返回一个空的 std::shared_ptr。

示例:

if (auto sharedPtr = weakPtr.lock()) {
    // 对象仍然存在,可以安全使用
    std::cout << "Object is alive: " << *sharedPtr << std::endl;
} else {
    // 对象已经被释放
    std::cout << "Object has been destroyed" << std::endl;
}

使用 std::weak_ptr 的场景
打破循环引用:

当两个对象相互持有对方的 std::shared_ptr 时,将其中一个替换为 std::weak_ptr。

缓存或观察者模式:

当需要缓存一个对象,但不希望缓存影响对象的生命周期时,可以使用 std::weak_ptr。

在观察者模式中,观察者可以持有被观察者的 std::weak_ptr,以避免影响被观察者的生命周期。

避免悬空指针:

std::weak_ptr 可以安全地检测对象是否已经被释放,从而避免悬空指针问题。

总结
在循环引用中,使用 std::weak_ptr 是为了打破循环,避免内存泄漏。std::weak_ptr 不会增加引用计数,因此不会影响对象的生命周期。通过合理使用 std::weak_ptr,可以解决 std::shared_ptr 的循环引用问题,同时保持代码的安全性和可维护性。

7.自定义智能指针类

#include <iostream>
#include <cstring> // for std::strlen and std::strcpy

template <typename T>
class SimpleSmartPointer {
private:
    T* ptr;          // 指向动态分配的资源
    int* ref_count;  // 引用计数

    // 释放资源
    void release() {
        if (ref_count) {
            (*ref_count)--;
            if (*ref_count == 0) {
                if (ptr) {
                    if constexpr (std::is_same_v<T, char>) {
                        delete[] ptr; // 如果是 char*,使用 delete[]
                    } else {
                        delete ptr;   // 其他类型使用 delete
                    }
                }
                delete ref_count;
            }
        }
    }

public:
    // 构造函数
    explicit SimpleSmartPointer(T* p = nullptr) : ptr(p), ref_count(new int(1)) {
        std::cout << "Resource acquired, ref count: " << *ref_count << std::endl;
    }

    // 拷贝构造函数
    SimpleSmartPointer(const SimpleSmartPointer<T>& other) : ptr(nullptr), ref_count(nullptr) {
        if constexpr (std::is_same_v<T, char>) {
            if (other.ptr) {
                ptr = new char[std::strlen(other.ptr) + 1]; // 深拷贝字符串
                std::strcpy(ptr, other.ptr);
            }
        } else {
            ptr = other.ptr; // 其他类型直接共享资源
        }
        ref_count = other.ref_count;
        (*ref_count)++;
        std::cout << "Resource copied, ref count: " << *ref_count << std::endl;
    }

    // 拷贝赋值运算符
    SimpleSmartPointer<T>& operator=(const SimpleSmartPointer<T>& other) {
        if (this != &other) {
            release();  // 释放当前资源

            if constexpr (std::is_same_v<T, char>) {
                if (other.ptr) {
                    ptr = new char[std::strlen(other.ptr) + 1]; // 深拷贝字符串
                    std::strcpy(ptr, other.ptr);
                } else {
                    ptr = nullptr;
                }
            } else {
                ptr = other.ptr; // 其他类型直接共享资源
            }
            ref_count = other.ref_count;
            (*ref_count)++;

            std::cout << "Resource assigned, ref count: " << *ref_count << std::endl;
        }
        return *this;
    }

    // 解引用运算符
    T& operator*() const {
        return *ptr;
    }

    // 箭头运算符
    T* operator->() const {
        return ptr;
    }

    // 析构函数
    ~SimpleSmartPointer() {
        release();
        std::cout << "Resource released, ref count: " << (ref_count ? *ref_count : 0) << std::endl;
    }

    // 获取引用计数
    int get_ref_count() const {
        return ref_count ? *ref_count : 0;
    }

    // 获取原始指针
    T* get() const {
        return ptr;
    }
};

int main() {
    // 测试 int 类型
    SimpleSmartPointer<int> ptr1(new int(10));
    std::cout << "ptr1 value: " << *ptr1 << ", ref count: " << ptr1.get_ref_count() << std::endl;

    {
        SimpleSmartPointer<int> ptr2 = ptr1;
        std::cout << "ptr2 value: " << *ptr2 << ", ref count: " << ptr2.get_ref_count() << std::endl;
    }

    std::cout << "ptr1 value: " << *ptr1 << ", ref count: " << ptr1.get_ref_count() << std::endl;

    // 测试 char* 类型
    SimpleSmartPointer<char> ptr3(new char[15]);
    std::strcpy(ptr3.get(), "Hello, World!");
    std::cout << "ptr3 value: " << ptr3.get() << ", ref count: " << ptr3.get_ref_count() << std::endl;

    {
        SimpleSmartPointer<char> ptr4 = ptr3;
        std::cout << "ptr4 value: " << ptr4.get() << ", ref count: " << ptr4.get_ref_count() << std::endl;
    }

    std::cout << "ptr3 value: " << ptr3.get() << ", ref count: " << ptr3.get_ref_count() << std::endl;

    return 0;
}

以上自定义类模拟标准库智能指针部分功能,并且能够正确处理字符串的深拷贝和释放。这个简单的智能指针类展示了如何通过引用计数来管理资源的生命周期。实际应用中,建议使用标准库中的 std::shared_ptr,它更加完善且经过充分测试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值