О передаче объекта в функцию —
обычно ссылка, НО!
1. Если библиотека живёт на указателях (Qt) — указатель.
void fillCombo(QComboBox* x) {} // хорошо
fillCombo(ui->comboHistory);
void fillCombo(QComboBox& x) {} // плохо
fillCombo(*ui->comboHistory);
2. Если возможен NULL — указатель. НО: существует паттерн «Null object», и он иногда бывает хорош.
// Хуже, но возможно
void import(AsyncRunner* asy) {
if (asy) {
asy->run([](){
doImport(x);
});
} else {
doImport(x);
}
}
import(nullptr);
// Лучше
void import(AsyncRunner& asy) {
asy.run([](){
doImport(x);
});
}
import(NoAsync::INST);
3. Если передаём буфер данных — указатель.
void write(size_t size, const char* data) {}
4. Если объект невелик — значение.
void save(std::string_view fileName) {}
Объект может быть велик, но для него существуют специальные регистры — тогда…
void transform(Matrix4 x) {}
Есть одна машина с такими регистрами, не помню только, какая. Xbox?
5. Идиома «by value + move», позволяющая избавиться от двух версий функции — Obj(string&) и Obj(string &&). Используется для объектов с простым перемещением и сложным копированием — обычно строк и структур STL.
Obj::Obj(std::string aName) : name(std::move(aName)) {}