C++智能指针用法及内存管理
一、内存管理中最长出现的问题:
1、空指针:空指针是一个不指向任何有效对象或函数的指针,其值为 NULL
(C)或 nullptr
(C++11 起)
2、野指针:野指针是指指向“不可用”或“无效”内存地址的指针,指向一个未知地方。
int* ptr; // 未初始化,ptr 是野指针
*ptr = 10; // 危险操作,访问非法地址int* ptr = malloc(sizeof(int));
free(ptr);
*ptr = 20; // ptr 成为野指针(悬空指针)int* func() {int x = 10;return &x; // 返回局部变量地址,函数结束后栈内存被释放,成为野指针
}
二、内存管理的方法
1、aoto(变量类型)
在 C++11 中,auto
关键字允许编译器根据变量的初始化表达式自动推导其类型,从而简化代码编写,尤其是在使用复杂类型时非常方便。使用场景通常有以下几个:
1、搭配STL容器使用
#include <vector>
std::vector<int> vec = {1, 2, 3};for (auto it = vec.begin(); it != vec.end(); ++it) {std::cout << *it << " ";
}
2、搭配智能指针使用
#include <memory>auto ptr = std::make_shared<int>(42); // shared_ptr<int>
auto uptr = std::make_unique<std::string>("hello"); // unique_ptr<string>
2、智能指针(内存申请)
C++ 中的 智能指针 是用于自动管理动态内存的类模板,它们通过封装裸指针(raw pointer),在对象生命周期结束时自动释放资源,从而避免内存泄漏和悬空指针等问题。最常用的智能指针如下,使用场景如下:
- 需要唯一控制资源时 → 使用
std::unique_ptr
- 多个对象共享资源时 → 使用
std::shared_ptr
std::unique_ptr
:同一时间只能有一个 unique_ptr
指向一个对象,使用make_unique创建一个对象。
std::shared_ptr
:多个 shared_ptr
可以指向同一个对象,使用make_shared创建一个对象。
std::weak_ptr:
不拥有对象,只是观察由 shared_ptr
管理的对象。
通过reset()函数可以手动释放资源,离开作用域以后也会自动释放资源
#include <memory>std::unique_ptr<int> ptr1 = std::make_unique<int>(42);
// std::unique_ptr<int> ptr2 = ptr1; // 编译错误:不可复制
std::unique_ptr<int> ptr2 = std::move(ptr1); // 合法:移动所有权std::shared_ptr<int> ptr1 = std::make_shared<int>(42);
std::shared_ptr<int> ptr2 = ptr1; // 合法:共享所有权
std::cout << "Use count: " << ptr1.use_count() << std::endl; // 输出 2ptr1.reset(); // 释放内存,ptr 变为 nullptr
3、NEW操作符(内存申请)
new
是一个用于动态分配内存的操作符,用于向堆去申请内存空间,它分配内存的大小由其后跟的数据类型决定。如,int* ptr = new int;
这行代码会在堆上分配一个能够存储一个整数的内存空间,并返回该内存块的首地址,将其赋值给指针 ptr。释放的时候需要调用delete ptr;去手动释放内存
int* p = new int; // 分配一个未初始化的 int
int* p2 = new int(42); // 分配并初始化为 42
delete p;
delete p2;
4、molloc(c语言内存申请)
分配指定大小(字节)的内存块,不初始化,需要手动管理内存
#include <stdlib.h>int* ptr = (int*)malloc(5 * sizeof(int)); // 分配能存储 5 个 int 的内存
if (ptr == NULL) {// 处理内存分配失败printf("Memory allocation failed\n");exit(EXIT_FAILURE);
}free(ptr); // 释放后 ptr 成为“悬空指针”
ptr = NULL; // 建议置为 NULL,防止后续误用