Как «вырезать и вставить» память?

Для «копирования и вставки» мы используем memcpy и memmove в зависимости от того, перекрываются ли src и dest, верно? Есть ли инкапсулированная функция «вырезать и вставить»? Если нет, существует ли относительно четко определенный способ добиться этого? Единственный способ, который я могу придумать, - это установить избыточную часть в 0 после memmove.

Чтобы уточнить код, с помощью mem_xxx, я хочу, чтобы массив с именем arr был «2345\0\0\0\0» вместо «234545\0\0», если использовать memmove.

char *arr = new char[8];
for ( int i = 2; i <= 5; i++ ) {
    arr[i] = char( i );
}
mem_xxx( arr, arr + 2, 5 - 2 + 1 ); 

Обратите внимание, что показанный вами код — это не C, а C++.

Some programmer dude 07.07.2024 12:27

Операции «вырезать» и «вставить» не имеют смысла на уровне абстракции необработанной памяти. При вырезании и вставке текста весь текст после этой точки сдвигается влево или вправо, чтобы освободить место для вставленного текста или не оставить пробелов при вырезании текста. Вы не можете вот так сдвинуть всю память «вправо» от какой-то точки влево или вправо.

user2357112 07.07.2024 12:29

Ближе всего в C++ к эффекту «комбинированного вырезания и вставки» может быть std::rotate.

user2357112 07.07.2024 12:32

Если вы хотите, вы можете написать memmovezap(), который заменяет исходный байт нулем после его копирования. Совершенно непонятно, зачем вам это нужно, но это несложно сделать.

tripleee 07.07.2024 12:32

Индексы массива 6 и 7 будут неинициализированы после вашего кода.

interjay 07.07.2024 12:35

@Atmo - это не код C!! Тег C недействителен.

0___________ 07.07.2024 12:54

У меня возник этот вопрос, когда я пытался поцарапать реализацию стека, имитирующую std::deque, где код stl src выполнял перемещение памяти, когда правый или левый конец «карты» все еще имеет большую неиспользованную часть. Обратите внимание, что «map» — это не std::map, а массив указателей на Tp, подробности см. в gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/….

PkDrew 07.07.2024 12:55

Я бы просто скопировал содержимое в память, а затем использовал memset, чтобы обнулить регион. Реализация этих функций быстрая, копирование слов вместо байтов и т. д. Я до сих пор не думаю, что это то, что вы действительно хотите сделать, поскольку нет никакого реального смысла устанавливать память в 0.

ThatGuy. exe 07.07.2024 13:16

Вы не инициализируете все элементы массива, а это значит, что некоторые значения будут неопределенными. А в C++ использование неопределенных значений каким-либо образом приводит к неопределенному поведению. Даже копирование этих значений в другое место будет использовать эти значения (иначе их невозможно скопировать).

Some programmer dude 07.07.2024 14:00

@PkDrew: Похоже, вы пытаетесь создать универсальный контейнер C++, когда говорите «имитировать std::deque». В этом случае о таких вещах, как memmove, совершенно не может быть и речи. Например, вы не можете запомнить std::string. Вы должны знать о std::move при написании такого контейнера. Это включает в себя понимание std::move, которое на самом деле не уничтожает перенесенный объект.

MSalters 08.07.2024 11:07

@MSalters, большое спасибо за ваш ответ, позвольте мне воспользоваться этой возможностью, чтобы подробнее рассказать об этом здесь. Игрушка представляет собой заранее выделенный массив указателей на элементы, обозначенные как Tp, т. е. Tp **arr = new Tp*[num_nodes]; Хитрость здесь в том, что вместо использования массива из головы мы используем его из середины, таким образом, для push_front() вы помещаете его влево, а для push_back() — вправо. Теперь, если какой-либо конец достигнут, но большая часть другого конца все еще свободна, в этом случае текущий действительный диапазон перемещается в сторону запасного конца, отсюда и этот вопрос.

PkDrew 08.07.2024 11:37

@PkDrew: Обратите внимание, что ни один из стандартных контейнеров не управляет содержащимися объектами с помощью указателей. Это довольно плохо для местности отсчета. А для контейнера типа двухуровневой очереди это важно. Когда это менее важно, std::list имеет гораздо более дешевый push_front/push_back.

MSalters 08.07.2024 12:41
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
12
174
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В библиотеке STL для C++ для этого есть функция rotate. Обратите внимание: вы спрашиваете просто о вращении элементов в заданном диапазоне.

#include <algorithm>

int main() {

    char arr[8]{};//char* arr = new char[8];
    for (int i = 2; i <= 5; i++) {
        arr[i] = char(i);
    }
    // first middle   last
    //   |   |        | 
    //  [0 0 2 3 4 5] 0 0
    //  [2 3 4 5 0 0] 0 0
    std::rotate(arr, arr + 2, arr + 6);
}

Если вас все еще интересует C, вы можете реализовать аналогичную функцию.

Иллюстрация работы алгоритма:
0 0 2 3 4 5 0 0
2 0 0 3 4 5 0 0
2 3 0 0 4 5 0 0
2 3 4 0 0 5 0 0
2 3 4 5 0 0 0 0

Спасибо за ваш ответ, приятель, да, это было бы то, что я ищу, а именно реализация, которая, надеюсь, будет введена в стандарт. Правда, для моей цели необходимо вращение влево или вправо, а массив, которым манипулируют, поддерживается внутри класса с помощью итераторов, поэтому я могу отметить допустимый диапазон.

PkDrew 08.07.2024 03:15

Да, выглядит необычно. Например, команда std::rotate(arr, arr + 4, arr + 6); вернет arr в предыдущее состояние, т.е. переместит элементы вправо на 2 позиции.

Konstantin Makarov 08.07.2024 04:38

Другие вопросы по теме