Fra*_*oVS 8 c++ multidimensional-array language-lawyer c++11
我可以确定以下代码可以工作吗?
int sum_array(int *array, size_t size)
{
int i;
int sum = 0;
for (i=0;i<size;i++)
sum += *(array+i);
return sum;
}
int main()
{
int two_d_array[4][3] = {{1,2,3}, {4,5,6}, {7,8,9}, {10,11,12}};
int sum = sum_array(&two_d_array[0][0], 12);
printf("%d", sum);
}
Run Code Online (Sandbox Code Playgroud)
虽然将4 x 3数组完全像12个元素的数组那样布置在内存中是合理的,但是可以保证吗?由于我似乎在欺骗类型系统,因此我不确定会出问题(例如,将填充添加到int [3])。
如果您可以详细说明如果我在数组中使用int以外的东西会发生什么,并提供标准的相关报价,则可以加分。
例如,将填充添加到int [3]
没有那危险。保证数组没有填充。内存布局本身得到保证,而指针算法在技术上未定义,如注释中提到的以下引号:expr.add / 4这样:
是否可以保证通过指针(T *)遍历2D数组(T [N] [M])?
不幸的是,从技术上讲,不是根据我对标准的理解。
这是标准的版本,std::accumulate该迭代对任何维数的多维数组的最内层元素进行迭代,就好像它是平面数组一样:
template<class T, unsigned size, class BinOp = std::plus<>>
auto arr_accumulate(
T (&arr)[size], std::remove_all_extents_t<T> init = {}, BinOp op = {})
{
if constexpr (std::is_array_v<T>) {
return std::accumulate(std::begin(arr), std::end(arr), init,
[&](const auto& l, const auto& r) {
return arr_accumulate(r, l, op);
}
);
} else {
return std::accumulate(std::begin(arr), std::end(arr), init, op);
}
}
// usage
int sum = arr_accumulate(two_d_array, 0);
Run Code Online (Sandbox Code Playgroud)
我还没有进行基准测试以查看是否有任何开销。在您的示例中使用编译时间常数输入时,总和是在编译时计算的。
另一个实现;仅适用于普通类型:
template<class T, unsigned size>
constexpr auto flat_size (T (&arr)[size]) {
using E = std::remove_all_extents_t<T>;
return sizeof arr / sizeof (E);
}
template<class T, unsigned size, class BinOp = std::plus<>>
auto arr_accumulate_trivial(
T (&arr)[size], std::remove_all_extents_t<T> init = {}, BinOp op = {})
{
using E = std::remove_all_extents_t<T>;
static_assert(std::is_trivially_copyable_v<E>);
std::array<E, flat_size(arr)> flat;
std::memcpy(flat.data(), arr, sizeof arr);
return std::accumulate(std::begin(flat), std::end(flat), init, op);
}
Run Code Online (Sandbox Code Playgroud)