C++学习笔记 06 数组
一、数组的创建
- 栈分配:int example[5]; 方法结束栈空间自动释放
- 堆分配:int* arr = new int[5]; 需要手动删除
#include<iostream>
int main() {
//1. 栈上分配数组空间,当前方法结束自动释放空间(栈空间内存有限),不必手动删除
int example[5];
//2. 堆上分配内存空间,可以通过return返回
int* arr = new int[5];
//堆数组必须手动delete
delete[] arr;
std::cin.get();
}
内存间接寻址(Memory Indirection)
一个指针,指向另一个指针
p1 --> p2 --> Arr
这会产生内存碎片和缓存丢失



在类对象地址上再去找到另一个堆中地址(本对象中属性在堆中的地址),这意味着我们基本要在代码里跳来跳去,所以,如果可以,你应该在栈上创建数组来避免这种情况,因为这样的内存跳跃肯定会影响性能。
二、计算数组大小的注意事项
1. C++ 11 std::array
内置数据结构,定义在C++11 标准库中。很多人喜欢用它来替代原生数组,因为有很多优点,有边界检查,记录数组大小。我们没有办法计算原生数组大小。
2. 原生计算
sizeof(变量名) / sizeof(类型)不可信。只对栈分配有效,对堆指针分配方式无效
#include<iostream>
#include<array>
//个人而言,总是用原生数组,大多数人都这么用,会更快一些。但如果你想安全,你可能想用std::array,
//std::array比原生数组安全得多,但我就喜欢危险
class Entity {
public:
//1. 必须是 static + const, 否则报错
static const int stackArrSize = 5;
int arr[stackArrSize];
//2. 也可以用constexpr
static constexpr int stackArrSize2 = 5;
int arr2[stackArrSize2];
//3. 堆数组指针以非常量分配大小不存在编译问题
int s1 = 5;
int* arrP = new int[s1];
//4. array
std::array<int, 5> arrayInstance;
//1. 栈上分配:栈上地址 + 偏移量。
int arrStack[5];
//2. 堆上分配,
int* arrHeep = new int[5];
Entity() {
//int 4个字节 * 5个元素 =20个字节 / int 4个字节
int count = sizeof(arrStack) / sizeof(int); // 5
//int指针大小 8个字节(64位) / int 4个字节
int count2 = sizeof(arrHeep) / sizeof(int); // 2
std::cout << count << " vs " << count2 << std::endl; //5 vs 2
//计算数组大小,用array当然比原生自定义数组会有额外开销,做边界检查,它也维护了一个整数类型size,实际你可能不需要size。
//通常这些额外开销是值得的。
std::cout << arrayInstance.size() << std::endl;
}
};
int main() {
Entity e;
//1. 栈上分配数组空间,当前方法结束自动释放空间(栈空间内存有限),不必手动删除
int example[5];
//2. 堆上分配内存空间,可以通过return返回
int* arr = new int[5];
//堆数组必须手动delete
delete[] arr;
std::cin.get();
}
总结:你要自己维护数组大小。这确实很麻烦,但是C++就是这样工作的,你必须去维护它。
栈中分配数组注意事项
当你在栈中为数组申请内存时,它必须是一个编译时就知道的常量,所以必须用static标记。这里还可以用constexpr表达式。类中常量表达式必须是静态的。



浙公网安备 33010602011771号