Как компилятор реализует передачу по значению и передачу по ссылке?

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

2 ответа

Решение

Это полностью зависит от того, как компилятор обрабатывает переменные (что можно назвать "средой").

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

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

Другие среды потребуют других подходов.

Передача по значению является наиболее простой формой передачи. И все реализовано с точки зрения передачи по стоимости в конце.

Если вы спрашиваете, что в действительности происходит, когда вызывается функция и аргументы передаются по значению, это зависит от платформы. Каждая платформа имеет свое собственное "соглашение о вызовах". В большинстве случаев происходит то, что первые несколько аргументов хранятся в регистрах процессора. Любые оставшиеся аргументы будут сохранены в предопределенном месте в стековом фрейме вызываемой функции, подобно локальным переменным. (То, как локальные переменные хранятся в кадре стека, определяется компилятором во время компиляции.) Поэтому, когда вызывается функция, все аргументы, которые должны быть сохранены в стеке, копируются туда; и любые аргументы, которые должны быть сохранены в регистрах, загружаются туда. Затем управление передается функции.

Что касается передачи по ссылке, если в языке есть указатели, передача по ссылке может быть выполнена путем передачи указателей по значению. Компилятор может просто выполнить этап предварительной обработки, где он "исключает" передачу по ссылке, выполняя следующий перевод:

  • Для каждого параметра функции, передаваемого по ссылке, он заменяет его указателем на этот тип, передаваемый по значению (например, void func(int &foo) -> void func(int *foo))
  • Для каждого использования этого параметра передачи по ссылке внутри этой функции, измените его на явное обращение к указателю (например, foo -> *foo) (за исключением того, что, если он снова передается по ссылке, не разыменовывайте его)
  • Каждый раз, когда вызывается эта функция, независимо от того, передается ли она в переменную pass-by-reference, я беру ее адрес явно (например, func(bar) -> func(&bar))
Другие вопросы по тегам