構造体(C++)は、関数の引数として渡したり、戻り値として返したりできる。
引数として渡す
const 参照で渡す
コピーのコストを避けたい場合や、読み取り専用で扱いたい場合は、const 参照で渡すことが多い。
#include <iostream>
struct Employee
{
int id {};
int age {};
double wage {};
};
void printEmployee(const Employee& employee)
{
std::cout << "ID: " << employee.id << '\n';
std::cout << "Age: " << employee.age << '\n';
std::cout << "Wage: " << employee.wage << '\n';
}
int main()
{
Employee joe { 14, 32, 24.15 };
printEmployee(joe);
}値渡しで渡す
構造体が小さく、コピーが安い場合は値渡しも自然である。 値渡しでは、関数内で受け取った引数は呼び出し元とは別オブジェクトになる。
struct Point
{
double x {};
double y {};
};
void translate(Point p)
{
++p.x;
++p.y;
}この場合、translate() の中で p を変更しても、呼び出し元のオブジェクトは変わらない。
戻り値として返す
構造体も、関数の戻り値として普通に返せる。
struct Point3d
{
double x {};
double y {};
double z {};
};
Point3d getZeroPoint()
{
return { 0.0, 0.0, 0.0 };
}return { 0.0, 0.0, 0.0 }; のように書くと、戻り値の型 Point3d に合わせて一時オブジェクトが作られて返される。
戻り値で返してもよい理由
構造体を値で返すとコピーが重そうに見えるが、C++ではコピー省略やムーブセマンティクスにより、効率よく返せることが多い。 そのため、単に「構造体だから戻り値で返すべきではない」とは限らない。
Point3d makePoint(double x, double y, double z)
{
return { x, y, z };
}参照を返す場合の注意
構造体への参照を返すこと自体はできるが、ローカル変数への参照を返してはいけない。
Point3d& getBadPoint()
{
Point3d p { 0.0, 0.0, 0.0 };
return p; // ダングリング参照
}このような参照は、関数終了時に参照先オブジェクトが破棄されるため危険である。
補足
- 読み取り専用の大きめの構造体は
const参照が使いやすい - 小さくてコピーが安い構造体は値渡しも十分有力
- 新しい構造体を作って返す設計では、戻り値で返すほうが自然なことが多い