Частично отсортируйте 2D-массив в стиле C с помощью std :: sort - PullRequest
1 голос
/ 25 мая 2020

Я наткнулся на этот вопрос относительно сортировки первых 2 строк массива целых чисел, очевидный способ, который пришел в голову, - использовать std::sort, поэтому я предложил решение вроде: 1005 *

Как вы можете увидеть здесь , он работает без ошибок и предупреждений.

Между тем @ Jarod42 указал, что это педантично неопределенное поведение в C ++, потому что эти являются указателями двух разных массивов.

Я склонялся к этому, учитывая, что в C это был бы хороший способ сделать это (без std::sort, std::begin и std::end, конечно), используя аналогичный метод доступа массив в строке, учитывая способ хранения 2D-массивов в C.

Мы договорились, что это будет неопределенное поведение, , но, как запомнил @SergeBallesta , почти все компиляторы принимают этот метод, поэтому следует ли его использовать?

А как насчет если используется указатель int(*mat)[3] на массив , будет ли pedanti c UB использовать std::sort таким образом?

//...
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
//...

1 Ответ

3 голосов
/ 25 мая 2020

Проблема возникает из-за того, как стандарт определяет тип массива (8.3.4 [dcl.array]):

Объект типа массива содержит непрерывно выделенный непустой набор N подобъекты типа T.

, но в нем явно не говорится, что непрерывный выделенный набор объектов одного типа может использоваться как массив.

По соображениям совместимости все компиляторы I Знайте, примите эту взаимность, но с педантичной точки зрения она не определена явно в стандарте и является неопределенным поведением.

Обоснование невзаимности заключается в том, что программа должна представлять модель. А в модели у объекта нет причин быть членом или более чем одним массивом одновременно. Так что стандарт этого не позволяет. Фактически, все (реальные) варианты использования, с которыми я когда-либо сталкивался для обработки 2D-массива, как если бы это был 1D-массив, были просто причинами оптимизации низкого уровня. А в современном C ++ программисту не следует заботиться о низкоуровневой оптимизации, а позволить компилятору это делать. это был 1D, вы должны спросить себя, в чем причина. Если вы используете устаревший код, не беспокойтесь об этом: компиляторы в настоящее время принимают его и даже в будущем, вероятно, продолжат работу, даже за счет специальных опций.

Но если вы пишете новый код, вам следует попробовать подняться на одну ступеньку выше (или назад) и задаться вопросом, что это означает на уровне модели . В большинстве случаев вы обнаружите, что массив изначально является 1D или 2D, но не одновременно. Как только это будет сделано, если производительность не критична, старайтесь всегда обрабатывать соответствующим образом . Или, что еще лучше, попробуйте использовать контейнеры из стандартной библиотеки вместо необработанных массивов.

Если вы используете критически важный для производительности код, в котором говорится, что любой смежный выделенный набор объектов является массивом, дает важное преимущество, сделайте это и задокументируйте его для будущих сопровождающих. Но делать это только после профилирования ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...