CppCoreGuidelines R.5 首选带作用域的对象,避免不必要的堆分配
11 February 2023
“Prefer scoped objects, don’t heap-allocate unnecessarily”
理由
有作用域范围的对象可以是局部的、全局的或成员的。这意味着,在作用域范围内,没有额外的分配释放开销。有作用域范围的对象的成员本省也是在作用域范围内,通过对象的构造析构函数管理生存周期。
例子
下面代码效率不高。每次调用都要申请释放内存。而且可能因为异常,导致内存泄漏。
void f(int n) { auto p = new Gadget{n}; // ... delete p; }
可以使用局部变量替代:
void f(int n) { Gadget g{n}; // ... }
强化
- 如果一个对象在函数中分配,又释放,可以考虑使用局部栈对象。
- 警告:如果一个局部的 unique 指针,shared 指针没有被移动、复制、重赋值、重置,但又不是声明为 const
例外
不要警告一个局部的指向一个没约束范围的数组的 unique 指针
例外
允许创建一个局部的常量的 unique_ptr<T[]>
指向堆中分配的缓存区。因为这是表示带范围的动态数组的有效方式。
例子
局部 const unique_ptr<T[]>
变量的合法案例:
int get_median_value(const std::list<int>& integers) { const auto size = integers.size(); // OK: declaring a local unique_ptr<T[]>. const auto local_buffer = std::make_unique_for_overwrite<int[]>(size); std::copy_n(begin(integers), size, local_buffer.get()); std::nth_element(local_buffer.get(), local_buffer.get() + size/2, local_buffer.get() + size); return local_buffer[size/2]; }