Мы не делаем C здесь ... и, пожалуйста, используйте идентификаторы с большим количеством букв, чем M и N.
#include <cstddef>
#include <iostream>
#include <algorithm>
#include <numeric>
#include <iterator>
template<typename T, std::size_t ROWS, std::size_t COLS>
void print_arr(T (&arr)[COLS][ROWS])
{
for (size_t row{}; row < ROWS; ++row) {
std::copy(&arr[row][0], &arr[row][0] + COLS,
std::ostream_iterator<T>{ std::cout, "\t" });
std::cout.put('\n');
}
std::cout.put('\n');
}
template<typename T, std::size_t ROWS, std::size_t COLS>
void kill_all_from_line_till_last(T (&arr)[COLS][ROWS], std::size_t kill_from)
{
std::fill(&arr[kill_from][0], &arr[kill_from][0] + (ROWS - kill_from) * COLS, T{});
}
int main()
{
constexpr size_t rows { 10 };
constexpr size_t columns { 10 };
int arr[rows][columns];
std::iota(&arr[0][0], &arr[0][0] + columns * rows, 1);
print_arr(arr);
kill_all_from_line_till_last(arr, 7);
print_arr(arr);
}
Вывод:
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70
71 72 73 74 75 76 77 78 79 80
81 82 83 84 85 86 87 88 89 90
91 92 93 94 95 96 97 98 99 100
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Версия Pseudo-C:
... с использованием std::memset()
выглядит почти так же:
#include <cstring>
template<typename T, std::size_t ROWS, std::size_t COLS>
void kill_all_from_line_till_last(T (&arr)[COLS][ROWS], std::size_t kill_from)
{
std::memset(&arr[kill_from][0], 0, (ROWS - kill_from) * COLS * sizeof(T));
}
, но вы можете использовать это только для POD.
Скорость:
Поскольку вы упомянули, что обнаружили, что std::fill()
слишком медленный для ваших нужд по сравнению с std::memset()
@ Sochuu:
сзаполнить, работает, но слишком медленно.Я хочу с memset
constexpr size_t rows { 10 };
constexpr size_t columns { 10 };
{
int arr[rows][columns];
std::iota(&arr[0][0], &arr[0][0] + columns * rows, 1);
print_arr(arr);
kill_all_from_line_till_last_fill(arr, 7);
print_arr(arr);
}
{
int arr[rows][columns];
std::iota(&arr[0][0], &arr[0][0] + columns * rows, 1);
print_arr(arr);
kill_all_from_line_till_last_memset(arr, 7);
print_arr(arr);
}
gcc
Сборка из gcc 9.1 (--std=c++14 -O3 -Wall
):
; ...
call void print_arr<int, 10ul, 10ul>(int (&) [10ul][10ul])
xor eax, eax
mov ecx, 15
mov rdi, rbx
rep stosq
mov rdi, rsp
call void print_arr<int, 10ul, 10ul>(int (&) [10ul][10ul])
; ...
call void print_arr<int, 10ul, 10ul>(int (&) [10ul][10ul])
xor eax, eax
mov rdi, rbx
mov ecx, 15
rep stosq
mov rdi, rsp
call void print_arr<int, 10ul, 10ul>(int (&) [10ul][10ul])
; ...
Как вы видите для обоихВ версиях между вызовами на print_arr()
генерируется точно такой же код.Компиляторы не настолько глупы.
Полный код: Godbolt Explorer Compiler Explorer
clang
То же самое для clang 8.3.0 (--std=c++14 -Ofast3 -Wall
), одинаковый код для обоих std::fill()
и std::memset()
:
; ...
mov rdi, rbx
call void print_arr<int, 10ul, 10ul>(int (&) [10ul][10ul])
xorps xmm0, xmm0
movups xmmword ptr [rsp + 376], xmm0
movups xmmword ptr [rsp + 360], xmm0
movups xmmword ptr [rsp + 344], xmm0
movups xmmword ptr [rsp + 328], xmm0
movups xmmword ptr [rsp + 312], xmm0
movups xmmword ptr [rsp + 296], xmm0
movups xmmword ptr [rsp + 280], xmm0
mov qword ptr [rsp + 392], 0
mov rdi, rbx
call void print_arr<int, 10ul, 10ul>(int (&) [10ul][10ul])
; ...
call void print_arr<int, 10ul, 10ul>(int (&) [10ul][10ul])
xorps xmm0, xmm0
movups xmmword ptr [rsp + 376], xmm0
movups xmmword ptr [rsp + 360], xmm0
movups xmmword ptr [rsp + 344], xmm0
movups xmmword ptr [rsp + 328], xmm0
movups xmmword ptr [rsp + 312], xmm0
movups xmmword ptr [rsp + 296], xmm0
movups xmmword ptr [rsp + 280], xmm0
mov qword ptr [rsp + 392], 0
mov rdi, rbx
call void print_arr<int, 10ul, 10ul>(int (&) [10ul][10ul])
; ...
Полный код: Godbolt Explorer Compiler Explorer
msvc
Microsoft cl 19.20 (/O2
):
; ...
call void print_arr<int,10,10>(int (&)[10][10])
xorps xmm0, xmm0
lea rcx, QWORD PTR arr$2[rsp]
xor eax, eax
movups XMMWORD PTR arr$2[rsp+280], xmm0
mov QWORD PTR arr$2[rsp+392], rax
movups XMMWORD PTR arr$2[rsp+296], xmm0
movups XMMWORD PTR arr$2[rsp+312], xmm0
movups XMMWORD PTR arr$2[rsp+328], xmm0
movups XMMWORD PTR arr$2[rsp+344], xmm0
movups XMMWORD PTR arr$2[rsp+360], xmm0
movups XMMWORD PTR arr$2[rsp+376], xmm0
call void print_arr<int,10,10>(int (&)[10][10]) ;
; ...
call void print_arr<int,10,10>(int (&)[10][10])
xorps xmm0, xmm0
lea rcx, QWORD PTR arr$1[rsp]
xor eax, eax
movups XMMWORD PTR arr$1[rsp+280], xmm0
mov QWORD PTR arr$1[rsp+392], rax
movups XMMWORD PTR arr$1[rsp+296], xmm0
movups XMMWORD PTR arr$1[rsp+312], xmm0
movups XMMWORD PTR arr$1[rsp+328], xmm0
movups XMMWORD PTR arr$1[rsp+344], xmm0
movups XMMWORD PTR arr$1[rsp+360], xmm0
movups XMMWORD PTR arr$1[rsp+376], xmm0
call void print_arr<int,10,10>(int (&)[10][10])
; ...
Полный код: Godbolt Explorer Compiler Explorer
Я думаю, что эксперимент может закончиться вэтот момент.