Каталог решений - Передача параметров по значению в языке 1С

Передача параметров по значению в языке 1С

Передача параметров по значению в языке 1С

В наличии

Все мы знаем, что в 1С можно написать такое:

Процедура ОбработатьОбъект(Знач Объект)
КонецПроцедуры

Т.е. тем самым мы передаем в процедуру параметр по значению
Далее в статье будут рассмотрены некоторые особенности передачи по значению объектов НЕпримитивных типов.

Категория:

Описание

Итак.

Все мы знаем, что в 1С можно написать такое:

Процедура ОбработатьОбъект(Знач Объект)

КонецПроцедуры

Т.е. тем самым мы передаем в процедуру параметр по значению.

 

Затем можем написать Эксперимент 1

Процедура ОбработатьОбъект(Знач Объект)

Объект = 3;
Сообщить(Объект);
КонецПроцедуры
А = 2;
Сообщить(А);
ОбработатьОбъект(А);
Сообщить(А);

И получим в итоге:

2

3

2

 

Далее можем сделать Эксперимент 2

Процедура ОбработатьОбъект(Знач Объект)

Объект.Очистить();
Сообщить(Объект.Количество());
КонецПроцедуры
А = Новый Массив;
А.Добавить(1);
А.Добавить(2);
А.Добавить(3);
А.Добавить(4);
Сообщить(А.Количество());
ОбработатьОбъект(А);
Сообщить(А.Количество());

И получим в итоге:

4

0

0

Но можем, наконец, провести Эксперимент 3:

Процедура ОбработатьОбъект(Знач Объект)

Объект = Новый Массив;
Сообщить(Объект.Количество());
КонецПроцедуры
А = Новый Массив;
А.Добавить(1);
А.Добавить(2);
А.Добавить(3);
А.Добавить(4);
Сообщить(А.Количество());
ОбработатьОбъект(А);
Сообщить(А.Количество());

И получим в итоге:

4

0

4

 

Выводы

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

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

А вот вывод из третьего эксперимента гораздо интереснее – использование Знач с коллекциями значений (и прочими НЕ примитивными типами) работает, все-таки, ожидаемо!!!

 

Если кому-то интересны причины таких результатов – читайте дальше.

 

Теперь разберем механику

 Для понимания механики обратимся сначала к трем более базовым темам программирования:

1)       механика создания переменных (на уровне компилятора/интерпретатора)

2)       работа с указателями на область памяти (я сознательно НЕ пишу выражение «ссылка на область памяти», чтобы не смешивать разные для 1С понятия в слове «ссылка»)

3)       механика передачи параметров при вызове процедур и функций

 

Начнем.

 

Механика создания переменных

В процессе выполнения программы при создании и инициализации переменной система (компилятор или интерпретатор) производит следующее:

— заведение в таблице переменных новой строки для этой новой переменной

— резервирование некоего участка памяти

— занесение в одну из ячеек созданной строки адреса этого участка памяти

— заполнение выделенного участка памяти требуемым значением

 

Далее.

Работа с указателями на область памяти

Для примитивных типов это (механизм создания переменных) работает один в один.

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

 

И наконец — Механика передачи параметров при вызове процедур и функций

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

Если в описании процедуры параметр описан со словом Знач, то перед помещением в стек система (компилятор/интерпретатор) производит

— выделение нового участка памяти

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

— помещение в стек указателя на выделенный участок памяти.

Тем самым – при возврате из процедуры содержимое старого участка памяти остается НЕТРОНУТЫМ.

 

Ну а далее все просто: во всех трех экспериментах при создании стека параметров произошло одно и то же — произошло копирование участка памяти со значением переменной А.

НО:

В эксперименте 1 скопировалось непосредственно значение 2.

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

Потому работа с массивом внутри процедуры привела к работе с самим массивом.

В эксперименте 3 произошло абсолютно то же самое, что и в эксперименте 2.

НО потом во вновь выделенный участок памяти был помещен указатель на вновь созданный массив!

Тем самым мы работали с новым массивом, а старый массив остался НЕТРОНУТЫМ.

 

Отсюда следует простой вывод – в 1С передача параметра по значению работает ожидаемо: копируется значение из участка памяти, на который указывает соответствующая ячейка таблицы переменных.

Т.е. для примитивных типов копируются непосредственно данные (т.е. само значение).

А вот для НЕ примитивных типов копируется лишь указатель на непосредственно данные.

 

Почему так

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

А это:

1) затратно в плане времени исполнения и использования памяти (ведь коллекция может быть большой)

2) не все НЕпримитивные типы в 1С могут быть сериализованы и десериализованы.

 

Как с этим жить

Один из обходных вариантов

— перед вызовом процедуры делать ЗначениеВСтрокуВнутр()/сериализацию в XML/помещать в хранилище значения/проч.,

— передать в процедуру полученную строку,

— а в самой процедуре вызвать ЗначениеИзСтрокиВнутр()/десериализацию из XML/извлечение из хранилища/проч..

Но, повторюсь, — не со всеми типами это сработает!

has been added to your cart:
Оформление заказа