К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как скопировать массив в 1С

Как правильно скопировать массив в 1С: оператор присваивания, цикл, Скопировать() и сериализация. Разбираем поверхностное и глубокое копирование с примерами кода.

Присваивание переменной НовыйМассив = СтарыйМассив; не создаёт копию массива в 1С — обе переменные начинают ссылаться на один и тот же объект в памяти. Изменение элемента через одну переменную немедленно отразится на другой. Это одна из самых частых причин трудноуловимых ошибок в коде, особенно когда массив передаётся между процедурами или хранится в реквизитах формы.

Реальная копия создаётся только явно: перебором элементов с добавлением в новый массив, универсальным методом через сериализацию значения или типовыми функциями из общих модулей. Выбор способа зависит от того, что лежит внутри массива — примитивные значения (числа, строки, даты) или ссылочные объекты (элементы справочников, структуры, другие массивы).

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

Почему присваивание не копирует массив

Массив в 1С — ссылочный тип данных. Переменная хранит не сами элементы, а указатель на область памяти, где находится массив. Когда вы пишете Массив2 = Массив1;, платформа копирует только указатель. В результате обе переменные работают с одним набором элементов.

Наглядный признак проблемы: вы добавляете элемент в «копию», а он появляется и в исходном массиве. Или очищаете один массив методом Очистить() — и пустеет второй. В отладчике это видно по совпадающему представлению значения у обеих переменных.

Важно понимать: та же логика действует для структур, соответствий, таблиц значений (у таблицы есть метод Скопировать()) и списков значений. Примитивные типы — число, строка, дата, булево — при присваивании копируются по значению, поэтому с ними такой проблемы нет.

Способ 1. Копирование перебором элементов в цикле

Самый прозрачный и контролируемый способ — создать новый массив и добавить в него все элементы исходного. Это даёт поверхностную копию, которой достаточно в большинстве прикладных задач.

ИсходныйМассив = Новый Массив;

ИсходныйМассив.Добавить("Первый");

ИсходныйМассив.Добавить("Второй");

Копия = Новый Массив;

Для Каждого Элемент Из ИсходныйМассив Цикл

Копия.Добавить(Элемент);

КонецЦикла;

После такого копирования Копия.Добавить("Третий") или Копия.Очистить() никак не затронут исходный массив. Способ хорош ещё и тем, что позволяет попутно фильтровать или преобразовывать элементы — например, пропускать пустые значения или добавлять только уникальные.

Учтите ограничение: если элементы массива — структуры или другие массивы, в копию попадут ссылки на те же вложенные объекты. Изменение вложенной структуры через копию изменит её и в оригинале. Для таких случаев нужна глубокая копия.

Порядок действий при копировании циклом
  1. 1
    Создайте пустой массив: Копия = Новый Массив;
  2. 2
    Переберите исходный массив циклом Для Каждого
  3. 3
    Добавьте каждый элемент в копию методом Добавить()
  4. 4
    Проверьте независимость: измените копию и убедитесь, что оригинал не изменился

Способ 2. Глубокое копирование через сериализацию

Когда внутри массива лежат структуры, соответствия или другие массивы, нужна глубокая копия. Универсальный приём — сериализация значения во внутреннюю строку и обратное восстановление:

Функция СкопироватьКоллекцию(Источник)

Возврат ЗначениеИзСтрокиВнутр(ЗначениеВСтрокуВнутр(Источник));

КонецФункции

Функция ЗначениеВСтрокуВнутр преобразует значение в строковое представление внутреннего формата, а ЗначениеИзСтрокиВнутр восстанавливает из него полностью независимый объект со всеми вложенными коллекциями. Приём работает для массивов, структур, соответствий, таблиц значений и их комбинаций.

Ограничения важно учитывать заранее. Сериализуются не все типы: например, значения, привязанные к контексту формы или содержащие несериализуемые объекты, могут вызвать ошибку. Ссылки на объекты базы данных (справочники, документы) сериализуются как ссылки — после восстановления они указывают на те же записи базы, что обычно и требуется. Сама операция не бесплатна по производительности: для больших массивов в цикле с тысячами итераций лучше искать алгоритмическое решение без постоянного копирования.

Способ 3. Типовые функции общих модулей

В конфигурациях на базе Библиотеки стандартных подсистем есть готовые механизмы копирования коллекций. В актуальных релизах используется функция ОбщегоНазначения.СкопироватьРекурсивно — она создаёт глубокую копию структуры, соответствия, массива или таблицы значений с учётом вложенности.

Копия = ОбщегоНазначения.СкопироватьРекурсивно(ИсходныйМассив);

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

Сравнение способов копирования

Цикл с Добавить()

Подходит для плоских массивов примитивов и ссылок. Быстро, наглядно, но не копирует вложенные коллекции.

ЗначениеВСтрокуВнутр / ЗначениеИзСтрокиВнутр

Глубокая копия почти любых коллекций. Медленнее, есть ограничения по сериализуемым типам.

ОбщегоНазначения.СкопироватьРекурсивно

Типовое решение в конфигурациях на БСП. Универсально, но требует наличия библиотеки в конфигурации.

Как выбрать способ под свою задачу

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

Если внутри массива — структуры с параметрами, которые вы планируете менять независимо (например, массив настроек для нескольких потоков обработки), нужна глубокая копия через сериализацию или рекурсивную функцию. Иначе изменение настройки в одной ветке алгоритма неожиданно повлияет на другую.

Маршрут решения

Как выбрать действие

Массив содержит только числа, строки, даты, булевоИспользуйте цикл с Добавить() — этого достаточно
Массив содержит ссылки на справочники и документыЦикл с Добавить(): ссылки копируются корректно, глубокая копия не нужна
Массив содержит структуры или вложенные массивы, которые будут изменятьсяПримените сериализацию или ОбщегоНазначения.СкопироватьРекурсивно
Копирование выполняется внутри массового цикла обработкиПересмотрите алгоритм: часто вместо копии можно создавать массив заново на каждой итерации

Проверка результата и типичные ошибки

Проверить независимость копии просто: после копирования добавьте в копию новый элемент или очистите её, затем сравните количество элементов в обоих массивах. Если ИсходныйМассив.Количество() не изменилось — копия независима. Для глубокой копии дополнительно измените значение во вложенной структуре копии и убедитесь, что в оригинале оно прежнее.

Контрольные точки

Как проверить результат

Количество элементов после изменения копии
Норма

У оригинала количество прежнее

Тревожный признак

Оригинал изменился вместе с копией — копирования не было

Вложенная структура в копии
Норма

Изменение вложенных значений не затрагивает оригинал

Тревожный признак

Вложенные данные общие — сделана только поверхностная копия

Поведение при передаче в процедуру
Норма

Процедура меняет свою копию, вызывающий код видит исходный массив

Тревожный признак

Изменения внутри процедуры видны снаружи — массив передан по ссылке

Отдельно помните о передаче массива в процедуры и функции. По умолчанию параметры передаются по ссылке: если внутри процедуры вы измените полученный массив, изменится и массив вызывающего кода. Если побочный эффект нежелателен, скопируйте массив в начале процедуры или объявите параметр с Знач — но учтите, что Знач для массива в ряде версий платформы не делает полную копию автоматически, надёжнее скопировать явно.

Типичные ошибки
01
Присваивание вместо копирования: обе переменные указывают на один массив, изменения дублируются
02
Цикл копирования для массива структур без глубокой копии: вложенные данные остаются общими
03
Сериализация большого массива в каждой итерации цикла: резкое падение производительности
04
Изменение массива-параметра внутри процедуры без копии: неожиданные побочные эффекты в вызывающем коде
05
Попытка скопировать массив с несериализуемыми объектами через ЗначениеВСтрокуВнутр: ошибка выполнения
Во многих задачах копию можно не делать вовсе: если массив нужен один раз для обхода, а исходный дальше не используется, работайте с оригиналом. Прежде чем внедрять глубокое копирование, проверьте, нельзя ли перестроить алгоритм так, чтобы каждая ветка логики формировала собственный массив с нуля.
ПЗ
Практическое замечание

Итог и частые вопросы

Ключевое правило одно: массив в 1С копируется только явно. Для плоских массивов достаточно цикла с Добавить(), для вложенных структур — сериализации или рекурсивной функции. Всегда проверяйте результат изменением копии и контролем оригинала, особенно при передаче массивов между процедурами.

Итог

Что важно запомнить

Присваивание создаёт вторую ссылку на тот же массив, а не копию. Плоский массив копируйте циклом, вложенные коллекции — через ЗначениеВСтрокуВнутр/ЗначениеИзСтрокиВнутр или типовую рекурсивную функцию. После копирования проверяйте независимость изменением копии.

Почему после «копирования» оба массива меняются одновременно?

Потому что оператор присваивания копирует ссылку, а не данные. Обе переменные указывают на один объект в памяти. Создайте новый массив и перенесите элементы циклом — тогда изменения станут независимыми.

Как скопировать массив структур, чтобы они были полностью независимы?

Нужна глубокая копия: используйте связку ЗначениеВСтрокуВнутр и ЗначениеИзСтрокиВнутр либо рекурсивную функцию, которая копирует каждую структуру и каждое вложенное значение. Простой цикл скопирует только ссылки на те же структуры.

Есть ли у массива встроенный метод Копировать(), как у таблицы значений?

Нет, у объекта «Массив» встроенного метода копирования нет — в отличие от таблицы значений со её методом Скопировать(). Копию массива создают вручную циклом или через сериализацию.

Нужно ли копировать массив, если в нём лежат ссылки на документы?

Сам массив — да, если планируете менять его состав независимо (добавлять, удалять элементы). А вот глубоко копировать сами ссылки не нужно: это указатели на записи базы данных, и обе копии массива корректно ссылаются на одни и те же документы.

Что быстрее: цикл или сериализация?

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

Как передать массив в процедуру, чтобы она его не испортила?

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