C++中的智能指针是一种用于管理动态分配内存的工具,它们可以自动释放内存,防止内存泄漏和悬挂指针问题。C++11标准引入了智能指针,包括std::unique_ptr
、std::shared_ptr
和std::weak_ptr
。每种智能指针都有不同的用途和特性。下面对它们进行详细介绍。
1. std::unique_ptr
std::unique_ptr
是独占所有权的智能指针,意味着某一时刻只能有一个unique_ptr
指向同一块内存。当unique_ptr
被销毁时,它所管理的对象会自动被删除。
特点:
- 独占所有权,不能共享。
- 自动释放内存,防止内存泄漏。
- 支持移动语义,但不支持复制语义。
用法:
cpp
#include <memory>
#include <iostream>
class MyClass {
public:
MyClass() { std::cout << "Constructor" << std::endl; }
~MyClass() { std::cout << "Destructor" << std::endl; }
void display() { std::cout << "Hello, World!" << std::endl; }
};
int main() {
// 创建unique_ptr
std::unique_ptr<MyClass> ptr1(new MyClass());
// 使用make_unique创建unique_ptr(C++14引入)
auto ptr2 = std::make_unique<MyClass>();
// 使用unique_ptr
ptr1->display();
// 转移所有权
std::unique_ptr<MyClass> ptr3 = std::move(ptr1);
if (!ptr1) {
std::cout << "ptr1 is null" << std::endl;
}
// ptr3自动释放内存
return 0;
}
2. std::shared_ptr
std::shared_ptr
是共享所有权的智能指针,可以多个指针指向同一块内存。当最后一个引用计数为零时,内存会被释放。它通过引用计数来管理内存。
特点:
- 共享所有权,多个
shared_ptr
可以指向同一个对象。 - 自动释放内存,防止内存泄漏。
- 引用计数管理内存,线程安全。
用法:
cpp
#include <memory>
#include <iostream>
class MyClass {
public:
MyClass() { std::cout << "Constructor" << std::endl; }
~MyClass() { std::cout << "Destructor" << std::endl; }
void display() { std::cout << "Hello, World!" << std::endl; }
};
int main() {
// 创建shared_ptr
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
// 复制shared_ptr
std::shared_ptr<MyClass> ptr2 = ptr1;
std::cout << "Reference count: " << ptr1.use_count() << std::endl; // 输出2
// 使用shared_ptr
ptr1->display();
// ptr1和ptr2自动释放内存
return 0;
}
3. std::weak_ptr
std::weak_ptr
是为了配合std::shared_ptr
而设计的一种智能指针,它不会影响引用计数。它用于解决循环引用的问题,当一个对象需要观测另一个对象,但不需要共享其所有权时使用。
特点:
- 不影响引用计数。
- 用于打破循环引用。
- 必须与
shared_ptr
一起使用,不能独立使用。
用法:
cpp
#include <memory>
#include <iostream>
class MyClass {
public:
MyClass() { std::cout << "Constructor" << std::endl; }
~MyClass() { std::cout << "Destructor" << std::endl; }
void display() { std::cout << "Hello, World!" << std::endl; }
};
int main() {
// 创建shared_ptr
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
// 创建weak_ptr
std::weak_ptr<MyClass> weakPtr = ptr1;
// 检查weak_ptr是否有效
if (auto ptr2 = weakPtr.lock()) {
ptr2->display();
} else {
std::cout << "Pointer is expired" << std::endl;
}
// ptr1自动释放内存
return 0;
}
智能指针的选择
std::unique_ptr
:适用于独占所有权的场景,资源只能由一个指针管理。std::shared_ptr
:适用于共享所有权的场景,多个指针可以同时管理同一个资源。std::weak_ptr
:适用于需要观察shared_ptr
管理的对象但不需要共享所有权的场景,通常用于避免循环引用。
注意事项
- 不要混合使用原始指针和智能指针:这样会导致难以追踪的内存管理问题。
- 避免循环引用 :
shared_ptr
的循环引用会导致内存泄漏,这时可以使用weak_ptr
来打破循环。 - 使用合适的智能指针 :根据实际需求选择
unique_ptr
、shared_ptr
或weak_ptr
。
智能指针是C++中管理动态内存的强大工具,正确使用它们可以显著提高代码的安全性和可维护性。