智能指针——独占指针

智能指针

独占指针 —— unique_ptr

unique_ptr 用于表示对一块动态内存的唯一所有权,其核心特性如下:

  1. 同一时刻只能有一个指针拥有该内存资源
  2. unique_ptr 超出作用域时,所管理的内存会被自动释放
  3. unique_ptr 不可拷贝(Copy),但可以移动(Move),用于显式转移所有权

创建方式

unique_ptr 有多种创建方式,但在实际开发中,最推荐使用 make_unique

独占指针的创建方式
// 1. 通过原始指针创建(不推荐)
cat* c_p1 = new cat("Tom");
std::unique_ptr<cat> u_c_p2(c_p1);

// 两个指针都能访问同一个对象
c_p1->cat_info();
u_c_p2->cat_info();

// 通过原始指针修改对象
c_p1->set_name("Jerry");
// unique_ptr 所指向的对象也随之改变
u_c_p2->cat_info();

// ⚠ 为了满足 unique_ptr 的独占语义,必须手动释放原始指针
c_p1 = nullptr;


// 2. 直接使用 new 创建(不推荐)
std::unique_ptr<cat> u_c_p3(new cat("Kitty"));
u_c_p3->cat_info();


// 3. 使用 make_unique 创建(最推荐)
std::unique_ptr<cat> u_c_p4 = std::make_unique<cat>("Mimi");
u_c_p4->cat_info();

说明:

  • 前两种方式容易引入重复释放、异常安全问题
  • make_unique 能保证异常安全,语义清晰,是现代 C++ 的推荐写法

传递方式

1. 值传递(不推荐)

值传递会涉及到所有权的转移
由于 unique_ptr 不允许拷贝,必须显式使用 std::move 将所有权转移给函数参数

这种方式会导致:

  • 调用后原指针失效
  • 每次传参都需要考虑所有权问题
  • 使用成本和心智负担较高
值传递示例
void Foo(std::unique_ptr<cat> c)
{
    c->cat_info();
}

int main()
{
    std::unique_ptr<cat> c1 = std::make_unique<cat>("Mimi");
    c1->cat_info();

    // 显式转移所有权,c1 不再拥有该指针
    Foo(std::move(c1));

    // c1 已经失效,继续使用会出错
    // c1->cat_info(); // 错误

    // 临时对象会隐式触发 move
    Foo(std::make_unique<cat>("111"));
}

2. 引用传递(推荐)

当函数不需要接管所有权,仅仅是使用对象时,应采用引用传递

为了防止误操作修改指针本身,推荐使用 const std::unique_ptr<T>&

  • 可以访问对象
  • 不能重置或转移指针
  • 保证所有权仍归调用方
引用传递示例
void Foo1(const std::unique_ptr<cat>& c)
{
    c->set_name("NewName");
    c->cat_info();

    // 不允许修改指针本身
    // c.reset(); // 错误
}

int main()
{
    std::unique_ptr<cat> c2 = std::make_unique<cat>("Jerry");
    Foo1(c2);

    c2->set_name("Tom");
    c2->cat_info();
}

3. 作为返回值

unique_ptr 非常适合作为函数返回值
编译器会自动使用移动语义(或 RVO),无需手动 std::move

这种方式:

  • 所有权语义清晰
  • 不存在资源泄漏
  • 支持链式调用
作为返回值示例
std::unique_ptr<cat> Foo2()
{
    return std::make_unique<cat>("Kitty");
}

int main()
{
    Foo2()->cat_info();
}

一句话总结

  • 拥有资源 → unique_ptr
  • 只使用、不接管 → const unique_ptr&
  • 需要转移所有权 → std::move
  • 创建对象 → make_unique
posted @ 2025-12-24 16:41  Ytytyty  阅读(3)  评论(0)    收藏  举报