C++存储二维数组到std::vector的高效实现及性能对比疑问
解决方案
1. 兼顾运行速度的正确实现
你遇到的编译错误本质是因为C++要求std::vector存储的元素必须支持拷贝/移动赋值,而原生数组不支持直接赋值操作。最优的实现方案是使用std::array封装二维数组,它和原生数组有完全一致的内存布局,无任何额外运行期开销,示例代码如下:
#include <vector> #include <array> int main() { // 内存布局和原生double[2][2]完全一致,连续存储无额外开销 std::array<std::array<double, 2>, 2> A = {{ {4, 7}, {2, 6} }}; std::vector<decltype(A)> B; // 提前预分配5个元素的空间,避免动态扩容带来的多余拷贝,进一步提升性能 B.reserve(5); for (int i = 1; i <= 5; ++i) { B.push_back(A); } return 0; }
如果你偏好原生数组的写法,也可以用结构体包裹原生数组,性能和上述方案完全一致:
struct Mat2x2 { double data[2][2]; }; std::vector<Mat2x2> B;
注意不要使用std::vector<std::vector<double>>实现,这种方案的子vector内存是分散分配的,缓存命中率极低,运行速度会比连续存储的方案慢很多。
2. 原生数组与std::array的性能对比
从缓存一致性和运行速度角度来看,开启O2及以上优化的release模式下,二者没有任何性能差异:
std::array是C++标准规定的聚合类型,内存布局和同尺寸原生数组完全相同,所有元素连续存储,没有额外的内存开销或者虚函数表指针。- 二者的CPU缓存行为完全一致:整个2x2数组会被一次性加载到缓存行中,访问元素时的缓存命中率没有区别,编译器生成的汇编指令也完全相同。
- debug模式下std::array可能会有边界检查的额外开销,但release模式下边界检查会被完全优化掉,和原生数组表现一致。
内容的提问来源于stack exchange,提问作者user590270
相关产品推荐
相关产品推荐

