为了解决传统指针相关的安全问题,C++11之后推出了智能指针。
如 std::unique_ptr,std::shared_ptr 和 std::weak_ptr。
它们会自动管理内存,减少了内存泄漏和其他常见错误的风险。
当你需要直接操纵内存地址时,指针仍然是有用的,但在现代C++编程实践中,应该尽量使用智能指针来管理动态内存。
std::unique_ptr
一个独占所有权的智能指针。一个 std::unique_ptr 对象拥有其指向的资源的唯一所有权。当 std::unique_ptr 被销毁时(通常是其所在的作用域结束时),它指向的对象也会被自动销毁。std::unique_ptr 不能被复制,但可以移动。
#include <memory>
void someFunction() {
std::unique_ptr<int> uptr(new int(10));
auto uptr2 = std::make_unique<int>(20);
*uptr = 5;
std::cout << *uptr;
std::cout << *uptr2;
std::unique_ptr<int> uptr3 = std::move(uptr2);
}
void someFunction1() {
std::unique_ptr<int> uptr(new int(10));
std::cout << *uptr << std::endl;
std::unique_ptr<int> uptr2 = std::move(uptr);
if (uptr) {
std::cout << "uptr is not null!" << std::endl;
}
}
std::shared_ptr
一个共享所有权的智能指针。多个 std::shared_ptr 可以指向相同的资源。资源的最后一个所有者被销毁时,指向的对象才会被销毁。 std::shared_ptr 内部使用一个引用计数机制来追踪多少个 shared_ptr 处于活动状态。
#include <memory>
class MyClass { };
std::shared_ptr<MyClass> sptr1(new MyClass());
auto sptr2 = std::make_shared<MyClass>();
std::shared_ptr<MyClass> sptr3 = sptr2;
void func(std::shared_ptr<MyClass> sptr) { }
std::shared_ptr<MyClass> getSharedPtr() { return sptr1; }
void anotherFunction() {
auto sptr = std::make_shared<int>(10);
{
std::shared_ptr<int> sptr2 = sptr;
}
std::cout << *sptr << std::endl;
}
std::weak_ptr
一种非独占所有权的智能指针,它指向由 std::shared_ptr 管理的对象。与 shared_ptr 不同,weak_ptr 不会增加对象的引用计数。这意味着 weak_ptr 不会阻止其指向的对象被销毁。它通常被用来解决 std::shared_ptr 之间可导致循环引用和内存泄漏的问题
#include <memory>
void thirdFunction1() {
std::shared_ptr<int> sptr = std::make_shared<int>(42);
std::weak_ptr<int> wptr = sptr;
if (auto temp = wptr.lock()) {
std::cout << *temp << '\n';
} else {
std::cout << "对象已被销毁\n";
}
}
void thirdFunction() {
auto sptr = std::make_shared<int>(10);
std::weak_ptr<int> wptr = sptr;
if (std::shared_ptr<int> sptrCopy = wptr.lock()) {
std::cout << *sptrCopy << std::endl;
} else {
std::cout << "资源已经被释放了" << std::endl;
}
}
使用注意事项
1、避免裸指针,优先使用智能指针来管理资源;
2、避免使用 new 和 delete,转而使用 std::make_unique 和 std::make_shared 来创建智能指针。
3、当使用 unique_ptr 时,表明对象拥有唯一所有权,通过 std::move() 来转移所有权;
4、使用 shared_ptr 来共享资源时,来共享对象所有权或实现观察者模式,要注意避免循环引用,否则可能导致内存泄漏;
5、使用 weak_ptr 来窥视 shared_ptr 或打破循环引用,避免 std::shared_ptr 的循环引用问题;
6、当需要传递智能指针给函数或从函数返回智能指针时,如果不需要转移所有权,则应传递引用(const std::unique_ptr<T>& 或 const std::shared_ptr<T>&)。这样避免增加引用计数或者导致不必要的所有权转移。
7、总要确保对于任何资源的管理都是明确的,避免资源泄露。
作为学习的知识点记录分享,欢迎大家补充