LoginSignup
1
1

More than 3 years have passed since last update.

その仮引数(構造体,クラス)は値か参照か[C,C++,C#]

Last updated at Posted at 2020-05-23

仮引数(parameter)の3つのパターン

C++のコードを眺めていると以下のような3つのパターンの構造体、クラスの仮引数に出くわします。

//①
void hoge( TEST test)
{
    test.a++;
}
//②
void hoge( TEST *test)
{
    test->a++;
}
//③
void hoge( TEST &test) 
{
    test.a++;
}

Cでは①②のパターン、
C#では①のパターンのみ出くわします。

上記3つのパターンの仮引数は各々の言語で以下のように分類されます。

C C++ C#
①(※) ①(※) ①(TESTが構造体の場合)
参照 ②③ ①(TESTがクラスの場合)

特に、①はC#は一見、値のように見えて(TESTがクラスの場合)参照されているということに注意してください。

実は①はC/C++の場合も値ではないかもしれません。

※構造体,クラスは基本的に値渡しされない

基本的にサイズが大きい構造体,クラスは値型として引数がコピーされるのではなく、
ポインタ渡し、または参照渡しをして使用されることが多いです。

よって、C/C++で①が使われることはほぼありません。

それにもかかわらず、①が使われる場面がCで割と出てきます。
そういうときは、
Cの場合、

typedef void* TEST;

voidポインタがTESTとして新しい名前に定義されている。
または

typedef struct {
    int    a;
} *TEST;

structのポインタがTESTとして新しい名前に定義されている。

C++の場合、

typedef shared_ptr<foo> TEST;

fooのポインタがTESTとして新しい名前に定義されている。

というように一見値型のように見えてポインタ型として、どこかで再定義されています。
(区別できるように、Cの場合 PTEST、C++の場合 TESTPtrというように接頭語、接尾語が付けられることが多い)

つまり、①~③の仮引数は十中八九、参照です。

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++をやると混乱します。

某漫画のように
「最初の入り口がオブジェクト指向なんだよね最近の子って」
「そうそう そんなんじゃ使いものにならねえっての」
となります。

1
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1