передача за in
посиланням здається логічно рівнозначною передачі за значенням.
Правильно.
Чи є якась перевага у виконанні?
Так.
Я вважав, що з внутрішньої сторони речей ref
параметр повинен принаймні копіювати фізичну адресу змінної, яка повинна бути такого самого розміру, як будь-яке типове посилання на об’єкт.
Немає вимоги, щоб посилання на об'єкт і посилання на змінну мали однаковий розмір, і немає вимоги, щоб будь-який з них був розміром машинного слова, але так, на практиці обидва це 32 біти на 32 розрядні машини та 64 біти на 64-розрядних машинах.
Мені незрозуміло, яке відношення до вас має "фізична адреса". У Windows ми використовуємо віртуальні адреси , а не фізичні адреси в коді користувацького режиму. За яких можливих обставин ви могли б уявити, що фізична адреса має значення у програмі на C #, мені цікаво знати.
Також не вимагається, щоб будь-яке посилання було реалізоване як віртуальна адреса сховища. Посилання можуть бути непрозорими дескрипторами таблиць GC у відповідній реалізації специфікації CLI.
чи перевага лише у більших конструкціях?
Зниження вартості передачі більших конструкцій є мотиваційним сценарієм для функції.
Зауважте, що немає жодної гарантії, що in
робить будь-яку програму насправді швидшою, і вона може робити програми повільнішими. На всі питання щодо результативності слід відповісти емпіричним дослідженням . Дуже мало оптимізацій, які завжди є перемогами ; це не оптимізація "завжди перемагай".
чи є якась закулісна оптимізація компілятора, яка робить її привабливою в іншому місці?
Компілятору та середовищу виконання дозволено робити будь-яку оптимізацію, яку вони обрали, якщо це не порушує правила специфікації C #. Наскільки мені відомо, ще не така оптимізація in
параметрів, але це не виключає такої оптимізації в майбутньому.
чому б мені не зробити кожен параметр вхідним?
Ну, припустимо, ви зробили int
параметр замість in int
параметра. Які витрати покладаються?
- сайт виклику тепер вимагає змінної, а не значення
- змінну неможливо зареєструвати. Ретельно відрегульована схема розподілу регістрів джиттера щойно закинула в неї гайковий ключ.
- код на сайті виклику більший, оскільки він повинен взяти посилання на змінну і помістити це в стек, тоді як раніше він міг просто пересунути значення в стек викликів
- більший код означає, що деякі вказівки стрибка в короткий час тепер могли стати вказівками стрибка у довжину, тому знову ж код тепер більший. Це впливає на всі види речей. Кеші заповнюються швидше, тремтіння має зробити більше роботи, тремтіння може вирішити не робити певних оптимізацій для більших розмірів коду тощо.
- на сайті виклику ми перетворили доступ до значення в стеку (або реєстрі) у непряме вказівник. Зараз цей вказівник, швидше за все, знаходиться в кеш-пам'яті, але все ж ми перетворили доступ до однієї інструкції до значення у доступ до двох інструкцій.
- І так далі.
Припустимо, це a, double
і ви змінили його на an in double
. Знову ж таки, тепер змінну неможливо зареєструвати у високоефективному регістрі з плаваючою комою. Це не тільки впливає на продуктивність , але і може змінити поведінку програми! C # дозволено робити арифметику з плаваючою системою з точністю вище 64-бітової, і зазвичай це робиться лише за умови, що плаваючі можна зареєструвати.
Це не безкоштовна оптимізація. Ви повинні виміряти його ефективність у порівнянні з альтернативними. Ваша найкраща ставка - це просто не робити великі конструкції насамперед, як пропонують керівні принципи проектування.
ref
використовується для передачі структур за допомогою посилання замість їх копіювання.in
означає, що структуру не слід модифікувати.