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