仮引数(parameter)の3つのパターン
C++のコードを眺めていると以下のような3つのパターンの構造体、クラスの仮引数に出くわします。
//①voidhoge(TESTtest){test.a++;}//②voidhoge(TEST*test){test->a++;}//③voidhoge(TEST&test){test.a++;}
Cでは①②のパターン、
C#では①のパターンのみ出くわします。
上記3つのパターンの仮引数は各々の言語で以下のように分類されます。
C | C++ | C# | |
---|---|---|---|
値渡し | ①(※) | ①(※) | ①(TESTが構造体の場合) |
参照(ポインタ)渡し | ② | ②③ | ①(TESTがクラスの場合) |
特に、①はC#は一見値渡しのように見えて(TESTがClassの場合)参照渡しされているということに注意してください。
実は①はC/C++の場合も値渡しではないかもしれません。
※構造体,クラスは基本的に値渡しされない
基本的にサイズが大きい構造体,クラスは値型として引数がコピーされるのではなく、
参照(ポインタ)渡しをして使用されることが多いです。
よって、C/C++で①が使われることはほぼありません。
それにもかかわらず、①が使われる場面がCで割と出てきます。
そういうときは、
typedefvoid*TEST;
voidポインタがTESTとして新しい名前に定義されている。
または
typedefstruct{inta;}*TEST;
structのポインタがTESTとして新しい名前に定義されている。
というように一見値型のように見えてポインタ型として、どこかで再定義されています。
C++は上記のような再定義はせず素直にクラスを定義し、③がよく使用されます。
つまり、①~③は十中八九、参照(ポインタ)渡しされています。
intやdoubleは単純ですが、
結局のところ、TESTのようなオリジナルの型の場合、定義を調べないと
その仮引数が値型として使われているか、参照型として使われているかはわかりません。
上記の関数に渡すときの型
C | C++ | C# | |
---|---|---|---|
① | [実体⇒実体] TEST test; hoge(test); or TEST *test; hoge(*test); ※ | [実体⇒実体] TEST test; hoge(test); or TEST *test = new TEST(); hoge(*test); ※ | [実体⇒参照] (クラスの場合) TEST test = new TEST(); hoge(test); |
② | [ポインタ⇒ポインタ] TEST *test; hoge(test) or TEST test; hoge(&test) | [ポインタ⇒ポインタ] TEST *test = new TEST(); hoge(test) or TEST test; hoge(&test) | - |
③ | - | [実体⇒参照] TEST test; hoge(test); or TEST *test = new TEST(); hoge(*test); | - |
あとがき
ポインタの概念をよく理解せず、オブジェクト指向のPython3やらC#をやって、C/C++をやると混乱します。
某漫画のように
「最初の入り口がオブジェクト指向なんだよね最近の子って」
「そうそう そんなんじゃ使いものにならねえっての」
となります。