项目

一般

简介

行为

支持 #466

打开

fortran 多维数组与 c++ 的区别

李立奎4 天 之前添加. 更新于 4 天 之前.

状态:
新建
优先级:
普通
指派给:
-
开始日期:
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 时,最需要注意的就是反转循环顺序以匹配列主序,否则缓存命中率会很差。

行为

导出 Atom PDF