C++ 智能指针是用于管理动态分配内存的对象,可以自动处理内存释放,防止内存泄漏和其他一些与内存管理相关的错误。智能指针是 C++11 标准中引入的重要功能,主要分为三种类型:std::unique_ptr
、std::shared_ptr
和 std::weak_ptr
。下面详细介绍每种智能指针的使用和特点。
1. std::unique_ptr
std::unique_ptr
是一种独占式的智能指针,意味着一个 std::unique_ptr
只能拥有一个指针。如果你想要转移指针的所有权,可以使用移动语义。
特点:
- 独占性:不能复制,只能移动。
- 自动释放:当
std::unique_ptr
被销毁时,它所持有的对象会被自动释放。 - 节省内存,防止内存泄漏。
使用示例:
#include <iostream>
#include <memory>
class Person {
public:
Person(const std::string& name) : name(name) {
std::cout << "Constructed: " << name << std::endl;
}
~Person() {
std::cout << "Destructed: " << name << std::endl;
}
private:
std::string name;
};
int main() {
// 创建一个 unique_ptr,管理指向 Person 的指针
std::unique_ptr<Person> person1(new Person("Alice"));
// person1 的所有权不能被复制
// std::unique_ptr<Person> person2 = person1; // 错误
// 移动所有权
std::unique_ptr<Person> person2 = std::move(person1);
if (!person1) {
std::cout << "person1 is now null." << std::endl;
}
return 0; // 当 person2 超出作用域时,Person 对象会被自动释放
}
2. std::shared_ptr
std::shared_ptr
是一种共享式的智能指针,可以让多个 std::shared_ptr
实例共享同一块动态分配的内存。它通过引用计数(reference count)机制来管理内存。
特点:
- 共享所有权:多个
std::shared_ptr
可以指向同一块内存。 - 引用计数:当一个
std::shared_ptr
被复制时,引用计数加一;当它被销毁时,引用计数减一。当计数为零时,内存被释放。 - 适合需要共享所有权的场景。
使用示例:
#include <iostream>
#include <memory>
class Person {
public:
Person(const std::string& name) : name(name) {
std::cout << "Constructed: " << name << std::endl;
}
~Person() {
std::cout << "Destructed: " << name << std::endl;
}
private:
std::string name;
};
int main() {
std::shared_ptr<Person> person1(new Person("Alice"));
std::cout << "person1 use_count: " << person1.use_count() << std::endl;
// 共享所有权
std::shared_ptr<Person> person2 = person1;
std::cout << "person1 use_count: " << person1.use_count() << std::endl;
std::cout << "person2 use_count: " << person2.use_count() << std::endl;
{
std::shared_ptr<Person> person3 = person2;
std::cout << "person1 use_count: " << person1.use_count() << std::endl;
std::cout << "person2 use_count: " << person2.use_count() << std::endl;
std::cout << "person3 use_count: " << person3.use_count() << std::endl;
} // person3 超出作用域,引用计数减 1
std::cout << "After person3 goes out of scope..." << std::endl;
std::cout << "person1 use_count: " << person1.use_count() << std::endl;
return 0; // 当最后一个 shared_ptr 被销毁时,Person 对象会被自动释放
}
3. std::weak_ptr
std::weak_ptr
是一种不拥有对象的智能指针,它与 std::shared_ptr
一起使用,目的是解决循环引用问题。std::weak_ptr
不增加引用计数,因此不会影响对象的生命周期。
特点:
- 弱引用:不拥有对象,不能直接访问需要先转化为
std::shared_ptr
。 - 解决循环引用:避免
std::shared_ptr
之间的循环引用导致的内存泄漏。
使用示例:
#include <iostream>
#include <memory>
class Person {
public:
Person(const std::string& name) : name(name) {
std::cout << "Constructed: " << name << std::endl;
}
~Person() {
std::cout << "Destructed: " << name << std::endl;
}
private:
std::string name;
};
class Team {
public:
std::shared_ptr<Person> member;
};
int main() {
std::shared_ptr<Team> team1(new Team());
{
std::shared_ptr<Person> person1(new Person("Alice"));
team1->member = person1; // Team 共享 Person
// 使用 weak_ptr 来避免循环引用
std::weak_ptr<Person> weakPerson = team1->member;
} // person1 超出作用域,自动释放
std::cout << "End of the program." << std::endl;
return 0; // 当 shared_ptr 被销毁,Team 对象会被自动释放
}
总结
std::unique_ptr
:用于独占式的内存管理,保证指向的对象只有一个所有者(不可以复制,使用移动语义)。std::shared_ptr
:用于共享式的内存管理,允许多个指针共享同一块内存,提供引用计数功能。std::weak_ptr
:解决循环引用问题的指针,不增加引用计数,需转成shared_ptr
后才能访问资源。