1. 内存分配位置
Java:
-
所有数组都是对象 ,必须通过
new在堆(heap) 上动态分配。 -
例如:
int[] arr = new int[10]; // 堆上分配
-
即使是局部变量,数组本身也在堆上,
arr这个引用变量在栈上。
C++:
- 支持栈上(自动存储)和堆上(动态存储)两种方式:
cpp
//栈上(推荐用于小数组、固定大小):
int arr[10]; // 栈上分配,编译时确定大小(C++标准要求数组大小为常量表达式)
//堆上(用于大数组或运行时确定大小):
int* arr = new int[10]; // 堆上分配,需手动 delete[]
delete[] arr;
- C++11 起也可用
std::vector<int>(更安全、推荐),它内部管理堆内存但自动释放。
2. 类型与对象模型
Java:
- 数组是一等对象 ,继承自
Object,有.length属性。 - 自动边界检查(越界抛出
ArrayIndexOutOfBoundsException)。 - 引用语义:赋值是复制引用,不是内容。
C++:
- 原生数组是类型的一部分 ,比如
int[10]是一个完整类型。 - 无边界检查(越界是未定义行为,可能导致崩溃或安全漏洞)。
- 数组名在多数上下文中退化为指针(
int*),但sizeof(arr)仍能获取总大小(仅限栈上数组)。 - 赋值不能直接进行(
arr1 = arr2编译错误),需用std::copy或std::array。
3. 生命周期与内存管理
Java:
- 自动垃圾回收(GC),无需手动释放。
- 数组不再被引用时,由 GC 回收。
C++:
- 栈上数组:作用域结束自动销毁。
- 堆上数组(
new[]) :必须显式delete[],否则内存泄漏。 - 推荐使用 RAII 容器如
std::vector或std::array避免手动管理。
4. 现代 C++ 替代方案
std::array<T, N>:栈上固定大小数组,支持拷贝、赋值、.size(),无退化为指针问题。
cpp
std::array<int, 10> arr;
std::vector<T>:动态大小,堆上管理,自动扩容和释放。
cpp
std::vector<int> vec(10); // 初始化10个元素
总结对比表
| 特性 | Java 数组 | C++ 原生数组 |
|---|---|---|
| 分配位置 | 总是在堆 | 可栈可堆 |
是否需要 new |
必须 | 栈上不需要 |
| 边界检查 | 有(运行时异常) | 无(未定义行为) |
| 生命周期管理 | GC 自动回收 | 栈:自动;堆:手动 delete[] |
| 能否直接赋值 | 引用赋值(浅拷贝) | 不能(需 memcpy 或容器) |
| 类型信息 | 有 .length |
无内建长度(需额外记录) |
| 推荐现代替代 | 无(数组本身已较安全) | std::array / std::vector |