Использование memcpy для копирования части массива и других инструментов для работы с памятью

Можно ли использовать memcpy для копирования части массива?

Скажем, например, у нас есть массив из 10 целых чисел. Можем ли мы создать новый массив и скопировать в него последние 5 целых чисел?

Существуют ли другие инструменты копирования/манипулирования памятью/массивом, доступные для использования с c/c++?


person FreelanceConsultant    schedule 07.02.2013    source источник
comment
Вы почти наверняка захотите использовать std::vector, а не массивы при написании кода на C++ (если у вас нет действительно веской причины хотеть контейнер с фиксированным размером во время компиляции, и в этом случае вы должны использовать std::array, а не встроенные массивы) .   -  person Mankarse    schedule 07.02.2013
comment
Необработанная память - это именно то, что мне нужно для этой цели: выполнение критично по времени и должно быть быстрым. std::vector будет недостаточно. (Или, по крайней мере, я предполагаю, что это будет медленнее.)   -  person FreelanceConsultant    schedule 07.02.2013
comment
@EdwardBird: вы предполагаете, что это будет медленнее, но производительность вектора может вас удивить. По крайней мере, выполните временные метрики, прежде чем полностью сбрасывать со счетов STL.   -  person AndyG    schedule 07.02.2013
comment
std::vector будет максимально быстрым, если вы правильно его используете.   -  person K-ballo    schedule 07.02.2013
comment
Пожалуйста, ознакомьтесь с мой любимый пример оптимизации компилятора (я написал его сам :-), прежде чем пытаться улучшить работу на низком уровне. . Компилятор сделает это за вас. В моем примере 10 строк шаблонного кода C++ превращаются в 4-5 машинных инструкций и выполняются за наносекунды.   -  person Bo Persson    schedule 07.02.2013


Ответы (2)


Можно ли использовать memcpy для копирования части массива?

Нет, в общем случае это невозможно. Вы можете сделать это только в том случае, если тип элементов в массиве имеет тривиальный макет.

Скажем, например, у нас есть массив из 10 целых чисел. Можем ли мы создать новый массив и скопировать в него последние 5 целых чисел?

int являются тривиальными типами, поэтому для этого конкретного случая это сработает:

int source[10] = { ::: };
int target[5];

std::memcpy( target, source + 5, 5 * sizeof(int) );

Существуют ли другие инструменты копирования/манипулирования памятью/массивом, доступные для использования с c/c++?

Конечно, весь набор алгоритмов в Стандартной библиотеке C++ будет работать с массивами. Вы используете указатели на первый и последний элементы в массиве как begin/end итераторы. Или, если вы используете C++11, просто std::begin|end( array ).

std::copy( source + 5, source + 10, target + 0 );

or

std::copy( std::begin(source) + 5, std::end(source), std::begin(target) );

Вот метафункция, которую вы можете использовать, чтобы проверить, является ли тип тривиальным, вместе с определением такой концепции: http://en.cppreference.com/w/cpp/types/is_тривиальный

person K-ballo    schedule 07.02.2013
comment
@EdwardBird: Да, например, невозможно скопировать объекты, у которых нет копирующих конструкторов. - person Mankarse; 07.02.2013
comment
@EdwardBird: Да, любой тип, кроме тривиального. Это включает в себя почти все типы, которые не являются простыми старыми типами C. - person K-ballo; 07.02.2013
comment
@EdwardBird гарантированно работает только для типов, которые имеют тривиальный конструктор, тривиальный деструктор, тривиальные конструкторы копирования и перемещения и тривиальные операторы присваивания копирования и перемещения. Это означает, что с указателями все в порядке, а с интеллектуальными указателями — нет. - person Dirk Holsopple; 07.02.2013
comment
@EdwardBird: указатели и массивы являются простыми типами C, так что да. Каждый фундаментальный тип тривиален, и совокупность (массив или структура) тривиальных типов также тривиальна. std::string и std::complex, с другой стороны, не тривиальны. - person K-ballo; 07.02.2013
comment
В принципе, это будет работать для всего, если вы напишете свои собственные конструкторы для копирования и присваивания? - person FreelanceConsultant; 07.02.2013
comment
@EdwardBird: Нет, это не сработает ни для чего с конструктором и/или назначением копирования, явным или неявным, что нетривиально. - person K-ballo; 07.02.2013
comment
Как насчет массива поплавков? Есть ли где-нибудь список типов, которые являются тривиальными? - person Adjwilley; 11.05.2019

memmove() служит для этой цели.

РЕДАКТИРОВАТЬ: memcpy() работает нормально. Это, вероятно, более обтекаемо в любом случае.

В этом примере код будет примерно таким:

int array1[10] = {0,1,2,3,4,5,6,7,8,9};
int array2[5] = {0,0,0,0,0};

memmove(array2, array1 + 5 * sizeof(int), 5 * sizeof(int));

Это скопирует 5 лотов int из массива 1, позиция 5, в массив 2, позиция 0.

person FreelanceConsultant    schedule 07.02.2013
comment
Этот ответ не имеет смысла. memmove идентичен memcopy, за исключением того, что он правильно обрабатывает перекрывающиеся диапазоны исходной и целевой памяти. Ответ не касается, когда можно скопировать часть массива, используя memcopy/memmove. - person Dirk Holsopple; 07.02.2013
comment
Итак, в этом случае memcpy является ответом. - person FreelanceConsultant; 07.02.2013
comment
memcpy это вопрос. Этот ответ ничего не говорит о том, какие типы массивов можно копировать с помощью memcpy. - person Dirk Holsopple; 07.02.2013
comment
array1 + 5 * sizeof(int) это место далеко от &array1[5] - person K-ballo; 07.02.2013
comment
Пожалуйста, объясните, а не добавляйте глупые комментарии. - person FreelanceConsultant; 08.02.2013