C++ передача аргументов по ссылке и указателю
В с ++
class bar
{
int i;
char b;
float d;
};
void foo ( bar arg );
void foo ( bar &arg );
void foo ( bar *arg );
это пример класса / структуры и функций
у меня есть несколько вопросов
- В чем разница между первым и вторым способами передачи аргумента в "asm", размер, скорость?
- как аргументы передаются в функции foo в каждом случае (в случае указателя я знаю, что указатель помещается в стек)
- при передаче аргументов, с точки зрения эффективности при (скорость, размер, предпочтительность), что лучше?
- что такое синтаксис intel 'asm', который соответствует каждому из способов передачи аргументов?
я знаю, что большинство говорят о "это не имеет значения для современных компиляторов и процессоров", но что, если мы говорим о старых процессорах или компиляторах?
заранее спасибо
5 ответов
Указатель и эталонные методы должны быть вполне сопоставимы (как по скорости, использованию памяти и генерируемому коду).
Передача класса напрямую вынуждает компилятор дублировать память и помещать копию bar
объект в стеке. Что еще хуже, в C++ есть всякие неприятные моменты (конструктор копирования по умолчанию и еще много чего), связанные с этим.
В C I всегда используются (возможно, const) указатели. В C++ вы, вероятно, должны использовать ссылки.
Любой разумный способ передачи по ссылке, вероятно, приведет к коду, включающему адреса объектов. Однако главная проблема заключается в том, что использование ссылок является более идиоматическим C++ и должно быть предпочтительным стилем; Вы действительно не должны видеть сырые указатели вообще в своем собственном коде.
Также обратите внимание, что передача по значению и по ссылке принципиально отличается в том смысле, что передача по ссылке позволяет вызываемому пользователю изменять аргумент. Если что, вы должны сравнивать f(bar)
с f(const bar &)
,
Указатели и ссылки различаются синтаксически и обычно идентичны во время выполнения и генерации кода. Что касается старых компиляторов... Я знал одну ошибку в DOS-компиляторе Borland 3 C++: он кэшировал значение int (передаваемое по ссылке) в регистр, изменял его и не изменял исходное значение в памяти. При передаче по указателю эквивалентный код работал как положено.
Тем не менее, я не думаю, что какой-либо современный компилятор может делать такие странные вещи (и Borland 5 исправил проблему)
Что касается стиля кода (кроме указателей и компромиссов между смарт-указателями), я обычно использую ссылки, если адрес не может быть НЕДЕЙСТВИТЕЛЕН по контракту функции, и использую указатели в противном случае.
Функция foo может модифицировать arg в случаях 2 и 3. В первых случаях компилятор может оптимизировать создание копии, поэтому очень сложно сравнивать процессор и использование памяти.
Если вы считаете, что рекомендуется проверять параметры указателя перед их использованием, тогда да, указатели вносят дополнительные издержки, поскольку ссылки не требуют такого тестирования.