
【値渡し、ポインタ渡し、参照渡し】C++でのポインタの話②(初級編)
はじまり
前回に引き続き元部員のsayuがポインタの話の第二回の記事を書きます!
今回の内容は、値渡し、ポインタ渡し、参照渡しの説明をします。
前回の記事の応用となっているので今回の記事の内容がわからない方は
前回の記事を下記のURLからご覧ください。
URL : https://note.com/fugedaku_47/n/nd1d8e1f48bd0?sub_rt=share_sb
前提条件
・メモリアライメントを無視
・64ビットで話を進める
値渡し
#include <iostream>
// 3をプラスする関数
void Plus(int hoge)
{
hoge += 3;
}
int main()
{
int hoge = 7;
Plus(hoge);
// 「7」と表示される
std::cout << hoge << std::endl;
return 0;
}
・解説
引数に指定した値そのものをコピーして関数に渡すので、
関数内で値を変更しても関数外では値は変更されない。
ポインタ渡し
#include <iostream>
// 3をプラスする関数
void Plus(int *hoge)
{
*hoge += 3;
}
int main()
{
int hoge = 7;
Plus(&hoge);
// 「10」と表示される
std::cout << hoge << std::endl;
return 0;
}
・解説
引数に指定した変数のアドレスを渡すことで、関数内から元の変数を直接
操作できます。そのため、関数内で値を変更すると、関数外の変数も変更
されます。
参照渡し
#include <iostream>
// 3をプラスする関数
void Plus(int &hoge)
{
hoge += 3;
}
int main()
{
int hoge = 7;
Plus(hoge);
// 「10」と表示される
std::cout << hoge << std::endl;
return 0;
}
・解説
引数に指定した変数そのものを参照(別名)として渡すので、関数内で
値を変更すると関数外の変数も変更されます。
別名とは
引数hogeは元の変数hogeの別名(同じ実体への新しい呼び名)として
扱われます。(すこし難しくなってくるので、まだ考えなくて良き)
実は…
上記で説明したポインタ渡し、参照渡しではメモリを余分に使用しているの事にお気づきでしょうか?
int は通常4バイトですが、int* は8バイトのサイズを持ちます。
ポインタを使用すると、実際には4バイトのデータをアクセスするために
8バイト分のメモリを確保していることになります。
このため、メモリを無駄に消費することになり、特に多数のポインタを
扱う場合、メモリ効率が低下する可能性があります。
と言う事でメモリ効率の良い使い方の例は下記の通りになります。
#include <iostream>
// 構造体でステータスを追加
struct Status
{
int attack; // 攻撃
int guard; // ガード
int stamina; // スタミナ
};
void Plus(Status* status)
{
status->attack += 100;
status->guard += 100;
status->stamina += 100;
}
int main()
{
Status status{30,30,30};
Plus(&status);
std::cout << status.attack << std::endl; // 「130」と表示される
std::cout << status.guard << std::endl; // 「130」と表示される
std::cout << status.stamina << std::endl; // 「130」と表示される
return 0;
}
・解説
構造体の Status は int 型を3つ持つため、合計12バイトになります。
この構造体を関数 Plus に渡す際、ポインタ(Status*)を使用します。
ポインタは8バイトのサイズを持ち、構造体のアドレスを指します。
これにより、関数内では構造体全体をコピーするのではなく、アドレスを
介して直接操作するため、メモリ効率が向上します。
特に大きな構造体を扱う場合、参照渡しを用いることで無駄なメモリ消費とコピー処理を削減できます。
ポインタ渡しと参照渡しの違い
ポインタ渡し
渡すのは「アドレス」
関数内で*を使って操作
少し複雑(アドレスと*を意識)
NULLを渡せる
参照渡し
渡すのは「別名」
通常の変数のように操作
直感的で簡単
NULLを渡せない(必ず有効な変数を渡す)
まとめ
※個人的な意見
・シンプルで分かりやすいコードを重視したい場合は 参照渡し。
・NULLやアドレス操作が必要で、柔軟性が求められる場合は
ポインタ渡し。
最後に
最後まで読んでいただきありがとうございます。
次回はtemplateの記事に書こうと思っています!
各種『ふゲだく!』公式アカウントなど
・X(旧Twitter)
https://twitter.com/fugedaku
・Instagram
https://www.instagram.com/fugedaku_official/
・YouTube
https://www.youtube.com/@fugedaku_official
・福岡情報ITクリエイター専門学校【公式サイト】
https://www.o-hara.ac.jp/senmon/school/fukuoka_it/