简体   繁体   English

使用 std::sort 对 C 样式的 2D 数组进行部分排序

[英]Partially sort a C-style 2D array with std::sort

I came across this question regarding sorting the first 2 lines of an array of integers, the obvious way that came to mind was to use std::sort so I proposed a solution like:我遇到了关于对整数数组的前两行进行排序的问题,想到的明显方法是使用std::sort所以我提出了一个解决方案,例如:

int mat[][3] = { {4, 5, 3},
                 {6, 8, 7},
                 {9, 5, 4},
                 {2, 1, 3} }; 


std::sort(std::begin(mat[0]), std::end(mat[1])); //sprting the first two rows

As you can see here it works without errors or warnings.正如您在此处看到的,它可以正常工作而不会出现错误或警告。

Meanwhile @Jarod42 pointed out that this is pedantically undefined behaviour in C++ because these are pointers of two different arrays.同时@Jarod42 指出,这是 C++ 中的迂腐未定义行为,因为这些是两个不同 arrays 的指针。

I inclined towards this given that in C this would be a good way to do it, (without the std::sort , std::begin and std::end of course), using a similar method of accessing the array in line, given the way 2D arrays are stored in C.我倾向于这样做,因为在 C 中这将是一个很好的方法,(当然没有std::sortstd::beginstd::end ),使用类似的方法来访问数组,鉴于二维 arrays 存储在 C 中的方式。

We agreed that it would be undefined behaviour, but as @SergeBallesta remebered , pretty much all compilers accept this method, so should it be used?我们同意这将是未定义的行为, 但正如@SergeBallesta remebered 所言,几乎所有编译器都接受这种方法,那么应该使用它吗?

And what about if one uses a int(*mat)[3] pointer to array , would it still be pedantic UB to use std::sort this way?如果一个人使用一个指向数组的int(*mat)[3]指针,那么以这种方式使用std::sort仍然是迂腐的 UB 吗?

//...
srand(time(0));

int(*mat)[3] = (int(*)[3])malloc(sizeof(int) * 4 * 3);
//or int(*mat)[3] = new int[4][3];

for(int i = 0; i < 4 ; i++)
    for(int j = 0; j < 3; j++)
        mat[i][j] = rand() % 9 + 1;

std::sort(std::begin(mat[0]), std::end(mat[1])); //sorting the first two rows
//...

The problem comes from the way the standard defines an array type (8.3.4 [dcl.array]):问题来自标准定义数组类型(8.3.4 [dcl.array])的方式:

An object of array type contains a contiguously allocated non-empty set of N subobjects of type T.一个数组类型的 object 包含一个连续分配的 N 个类型为 T 的子对象的非空集合。

but it does not explicitely says that a contiguous allocated set of objects of the same type can be used as an array.但它并没有明确说明可以将一组连续分配的相同类型的对象用作数组。

For compatibility reasons all compilers I know accept that reciprocity, but on a pedantical point of view, it is not explicitely defined in the standard and is Undefined Behaviour.出于兼容性原因,我知道的所有编译器都接受这种互惠,但从迂腐的角度来看,它没有在标准中明确定义,而是未定义的行为。

The rationale behind the non reciprocity is that a program is expected to represent a model.非互易性背后的基本原理是,程序应代表 model。 And in the model, an object has no reason to be member or more than one array at the same time.在 model 中,一个 object 没有理由同时成为成员或多个阵列。 So the standard does not allow it.所以标准不允许。 In fact all the (real world) use cases I have ever encountered for handling a 2D array as if it was a 1D one were just low level optimization reasons.事实上,我遇到的所有(现实世界)用例都将 2D 数组当作 1D 数组处理,这只是低级优化原因。 And in modern C++, the programmer should not care for low level optimization but let the compiler handle it.而在现代 C++ 中,程序员不应该关心低级优化,而是让编译器处理它。

The following it only my opinion.以下仅代表我个人看法。

When you find yourself processing a 2D array as if it was a 1D one, you should ask yourself for the reason.当您发现自己像处理一维数组一样处理二维数组时,您应该问问自己原因。 If you are using a legacy code, do not worry about it: compilers currently accept it, and even in the future will probably continue, even at the price of special options.如果您使用的是遗留代码,请不要担心:编译器目前接受它,甚至将来可能会继续使用它,即使以特殊选项为代价。

But if you are writing new code, you should try to move one step higher (or back) and wonder what it represents at the model level .但是,如果您正在编写新代码,您应该尝试向上(或向后)移动一步,并想知道它在 model 级别代表什么。 Most of the time, you will find the the array is intrisically 1D or 2D but not both.大多数时候,您会发现数组本质上是一维或二维的,但不是两者兼而有之。 Once this is done, if performance is not critical try to always handle it the conformant way .完成此操作后,如果性能不重要,请尝试始终以一致的方式处理它。 Or even better, try to use containers from the standard library instead of raw arrays.或者更好的是,尝试使用标准库中的容器而不是原始 arrays。

If you are in a performance critical code where saying that any contiguous allocated set of objects is an array provides an important benefit, do it and document it for future maintainers.如果您在性能关键代码中说任何连续分配的对象集是一个数组提供了重要的好处,请执行此操作并将其记录下来以供将来的维护者使用。 But only do that after profiling...但只有在分析之后才这样做......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM