行为
支持 #466
打开fortran 多维数组与 c++ 的区别
状态:
新建
优先级:
普通
指派给:
-
开始日期:
2026-01-15
计划完成日期:
% 完成:
0%
预期时间:
#2:
描述
从 C++ 背景来看,Fortran 多维数组有几个关键区别需要特别注意,尤其是内存布局的差异会直接影响代码逻辑和性能。
1. 内存布局:列主序 vs 行主序
这是最本质的区别:
-
C++:行主序(Row-major)
int arr[3][4]; // 内存中:arr[0][0], arr[0][1], ..., arr[0][3], arr[1][0], ... // 遍历性能:for(i) for(j) 访问 arr[i][j] 是连续的 -
Fortran:列主序(Column-major)
integer :: arr(3,4) ! 内存中:arr(1,1), arr(2,1), arr(3,1), arr(1,2), ... ! 遍历性能:do j = 1,4; do i = 1,3; 访问 arr(i,j) 是连续的
影响:嵌套循环顺序需要反转,否则性能会大幅下降。
2. 下标起始:默认 1-based
integer :: a(10) ! 索引 1..10
integer :: b(0:9) ! 可以显式指定 0..9
integer :: c(-5:5) ! 甚至可以是负数范围
3. 数组声明语法
! Fortran(维度在后)
real :: matrix(10, 20) ! 10行20列
real, allocatable :: dyn(:,:) ! 可分配数组
! C++(维度在前)
double matrix[10][20];
std::vector<std::vector<double>> dyn;
4. 数组整体操作
Fortran 支持直接的数组运算,无需循环:
real :: a(100), b(100), c(100)
a = b + c ! 逐元素相加
a = sqrt(b) ! 逐元素开方
where (b > 0) a = log(b)
C++ 需要 std::transform 或手写循环。
5. 数组切片
! 提取子数组
real :: big(100, 100), small(10, 10)
small = big(1:10, 21:30) ! 直接切片复制
6. 函数传参:形状信息可保留
subroutine process(arr)
real, intent(inout) :: arr(:,:) ! 假设形状,接收任意大小
! 可通过 size(arr,1) 获取各维度
end subroutine
! 调用
call process(my_array) ! 无需额外传递维度信息
C++ 中通常需要模板或额外参数传递维度。
7. 动态数组
real, allocatable :: arr(:,:)
allocate(arr(n, m))
...
deallocate(arr)
! 自动重新分配
arr = reshape(source_array, [new_n, new_m])
总结对比表¶
| 特性 | Fortran | C++ |
|---|---|---|
| 内存顺序 | 列主序 | 行主序 |
| 默认索引 | 1-based | 0-based |
| 数组运算 | 原生支持 | 需库/手动实现 |
| 切片 | 语法级支持 | 需指针/引用操作 |
| 传参 | 可保留形状信息 | 通常退化或需模板 |
| 性能敏感 | 按列遍历 | 按行遍历 |
建议:从 C++ 转向 Fortran 时,最需要注意的就是反转循环顺序以匹配列主序,否则缓存命中率会很差。
行为