最推荐使用 std::unique_ptr<T[]> 管理动态数组,因其能自动调用 delete[] 避免内存泄漏;若需共享所有权,可用带自定义删除器的 std::shared_ptr;但多数情况下应优先选用 std::vector,因其兼具自动管理、丰富接口与优良性能。

在C++中,管理动态数组与智能指针结合使用,最直接且推荐的方式是利用
std::unique_ptr<T[]>
delete[]
std::shared_ptr
std::vector
当我们需要在堆上分配一个动态数组时,传统的做法是使用
new T[size]
delete[]
delete
delete[]
1. std::unique_ptr<T[]>
这是管理动态数组最直接、最安全的方法,尤其当你确定数组的生命周期与智能指针的生命周期完全绑定,且没有其他地方需要共享该数组时。
std::unique_ptr
std::unique_ptr<T[]>
delete[]
立即学习“C++免费学习笔记(深入)”;
#include <memory>
#include <iostream>
void process_data(int* arr, size_t size) {
for (size_t i = 0; i < size; ++i) {
arr[i] *= 2;
}
}
int main() {
// 创建一个包含10个int的动态数组
std::unique_ptr<int[]> arr_ptr = std::make_unique<int[]>(10); // C++14及更高版本推荐
// 或者 C++11 风格:
// std::unique_ptr<int[]> arr_ptr(new int[10]);
for (int i = 0; i < 10; ++i) {
arr_ptr[i] = i + 1; // 像普通数组一样访问元素
}
std::cout << "Original array elements: ";
for (int i = 0; i < 10; ++i) {
std::cout << arr_ptr[i] << " ";
}
std::cout << std::endl;
// 可以获取原始指针传递给C风格API
process_data(arr_ptr.get(), 10);
std::cout << "Processed array elements: ";
for (int i = 0; i < 10; ++i) {
std::cout << arr_ptr[i] << " ";
}
std::cout << std::endl;
// arr_ptr超出作用域时,会自动调用 delete[] arr_ptr.get()
return 0;
}std::make_unique<int[]>(10)
new
2. std::shared_ptr
如果你的动态数组需要被多个
std::shared_ptr
std::shared_ptr
delete
delete[]
std::shared_ptr<int> shared_arr(new int[10]);
shared_arr
delete
delete[]
正确的做法是提供一个自定义的删除器(通常是一个lambda表达式),明确告诉
std::shared_ptr
#include <memory>
#include <iostream>
#include <vector> // 后面会提到
int main() {
// 使用自定义删除器管理动态数组
std::shared_ptr<int> shared_arr(new int[10], [](int* p) {
std::cout << "Custom deleter called for shared_arr, deleting array." << std::endl;
delete[] p;
});
for (int i = 0; i < 10; ++i) {
shared_arr.get()[i] = (i + 1) * 10; // 通过get()获取原始指针访问
}
// 可以创建其他shared_ptr实例共享所有权
std::shared_ptr<int> another_shared_arr = shared_arr;
std::cout << "Shared array elements: ";
for (int i = 0; i < 10; ++i) {
std::cout << shared_arr.get()[i] << " ";
}
std::cout << std::endl;
// 当所有shared_ptr实例都超出作用域时,自定义删除器会被调用一次
return 0;
}这里有个细节,
std::shared_ptr<int>
std::shared_ptr<int[]>
std::shared_ptr
std::unique_ptr
std::shared_ptr
get()
3. std::vector
我个人认为,除非有非常特殊的原因,比如需要与C风格API高度兼容,或者对内存布局有极致的控制需求,否则
std::vector
#include <vector>
#include <iostream>
int main() {
std::vector<int> vec(10); // 创建一个包含10个int的动态数组
for (int i = 0; i < 10; ++i) {
vec[i] = i * 100; // 像普通数组一样访问元素
}
std::cout << "Vector elements: ";
for (int i = 0; i < vec.size(); ++i) {
std::cout << vec[i] << " ";
}
std::cout << std::endl;
// vec超出作用域时,会自动释放内存
return 0;
}std::vector
std::unique_ptr<T>
这是一个非常常见的误区,我见过不少新手会犯这样的错误。核心问题在于
std::unique_ptr<T>
std::unique_ptr<T[]>
当你声明
std::unique_ptr<T> ptr(new T[size]);
unique_ptr
T
ptr
delete ptr.get();
然而,如果你用
new T[size]
delete[] ptr.get();
所以,当
delete
new[]
简单来说,
delete
delete[]
delete
delete[]
new[]
delete[]
delete
// 错误的示例,会导致未定义行为! std::unique_ptr<int> bad_array_ptr(new int[10]); // 当 bad_array_ptr 析构时,会调用 delete (int*) 而不是 delete[] (int*) // 这就是问题所在。
所以,请务必记住:管理动态数组,要用
std::unique_ptr<T[]>
std::unique_ptr<T>
std::shared_ptr
正如前面提到的,
std::shared_ptr
std::unique_ptr
std::shared_ptr
new T[size]
最关键的注意事项就是:不要忘记自定义删除器,并且确保删除器调用的是 delete[]
// 错误示范:没有自定义删除器
// std::shared_ptr<int> my_shared_array(new int[5]); // 同样是未定义行为!
// 正确示范:使用lambda表达式作为自定义删除器
std::shared_ptr<int> my_shared_array_correct(new int[5], [](int* p) {
std::cout << "Custom deleter for shared_ptr array called." << std::endl;
delete[] p; // 确保是 delete[]
});自定义删除器是一个可调用对象(函数指针、函数对象或lambda),它接受一个原始指针作为参数,并负责释放该指针指向的资源。
std::shared_ptr
如果你忘记提供自定义删除器,
std::shared_ptr
delete
std::unique_ptr<T>
此外,需要注意的是,当使用
std::shared_ptr
get()
my_shared_array_correct.get()[i]
std::shared_ptr<T>
operator[]
T
虽然
std::shared_ptr
std::shared_ptr
std::unique_ptr<T[]>
std::vector
std::vector
在我看来,这是一个非常实际的问题,也是现代C++编程中一个重要的设计决策。我几乎可以说,在绝大多数情况下,
std::vector
new T[]
以下是我个人总结的一些理由,说明为什么
std::vector
std::vector
new
delete[]
std::vector
std::vector
new T[]
std::sort
std::for_each
at()
operator[]
capacity()
reserve()
shrink_to_fit()
std::vector<T>
T
std::vector
std::vector
std::vector
std::vector
那么,什么时候会考虑智能指针管理 new T[]
T*
void*
std::unique_ptr<T[]>::get()
std::shared_ptr<T>::get()
std::vector<T>::data()
std::vector
new T[size]
new T[]
std::unique_ptr<T[]>
std::shared_ptr<T>
总而言之,我的建议是:总是从 std::vector
std::vector
std::unique_ptr<T[]>
std::shared_ptr
new T[]
以上就是C++如何在智能指针中管理动态数组的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号