C++における関数へ変数を渡すときの話

こんにちは、ぷないしんです。

 

関数への値を渡す方法の話をしたいと思います。

 

関数へ値を渡すときの記述方法ですが下記の三つがあるみたいです。

 

①普通の渡し方(値渡しと言われる)

②ポインタ渡し

③参照渡し

 

普通の渡し方とポインタ渡しはCにもありますが、参照渡しについてはC++特有の渡し方です。

 

という事で上記の三つを詳しく見ていきましょう。

 

①普通の渡し方

まずコードを記述してみます。

#include <iostream>

using namespace std;

void kansu(int a){
    a = a + 1;
    cout << a << "\n";
}

int main(){
    int x = 1 ;
    cout << x << "\n";
    kansu( x );
    cout << x << "\n";
}

これで実行結果は

f:id:punainen:20210315132556p:plain

関数1

こうなりました。

渡された数値を+1し、その値を出力するだけの関数を作成しました。

 

ここで注目してほしいのはxの値は関数では+1されずに1のままという事です。

 

これは何を意味しているかというと

xの値を直接処理しているのではなくコピーしたものを処理しているという事です。

なのでコピーされた引数の値をいくら変更しようが、関数を呼び出した側の変数の処理は行われません。

 

調べてみたところ、わざわざコピーを作成しているので、引数が大きな値であれば処理に時間がかかるので、そのような可能性があるときにはこの渡し方は推奨されないとのことです。

 

次に②のポインタ渡し

例によってコードの記述から行います

#include <iostream>

using namespace std;

void kansu(int* a){
    *a = *a + 1;
    cout << *a << "\n";
}

int main(){
    int x = 1 ;
    cout << x << "\n";
    kansu( &x );
    cout << x << "\n";
}

①との差異は

・関数の定義時にint*

・関数の中身の変数それぞれにa*

・メイン関数で関数呼び出し時、変数に&x

 

そして結果の方は

 

f:id:punainen:20210315134319p:plain

関数2

こうなりました。

 

本来はnullチェックというものを行わないといけないようなのですが、それはまた別の機会にお話しするとして結果の方に注目してみましょう。

 

関数を呼び出した後にxの値が書き変わっているではありませんか、これはつまり

関数の呼び出し元の変数を書き換えることができるということですね。

 

ポインタなのでメモリ上のアドレスを渡しているという言い方になります。

渡してもらったアドレスを関節的に参照することによってこのような処理になっています。

 

 

そして③参照渡しですがこれはCには存在せず、C++に独自に実装されている渡し方で、下記の様に記述します。

#include <iostream>

using namespace std;

void kansu(int& a){
    a = a + 1;
    cout << a << "\n";
}

int main(){
    int x = 1 ;
    cout << x << "\n";
    kansu( x );
    cout << x << "\n";
}

 

結果の方は

f:id:punainen:20210315134319p:plain

②のポインタ渡しと同じ結果ですね。

 

この渡し方で注目してほしいのは、記述の方法です。

 

なんと関数を定義するときにint&とするだけで、ポインタ渡しと同じ結果になったではありませんか。

 

どういう渡し方なのかという元の変数に別の名前を付ける渡し方と言われています。

 

どういうことかというと

 

変数Nipponに対して参照渡しで(int& Japan)で渡すと変数Nipponも変数Japanも同じメモリアドレスを指す事になります。

 

なので呼び出し元の変数にアクセスし、書き換えることが出来るという訳です。

 

つまり、参照渡しは変数を関数で受け渡す時にポインタ渡しの記述を簡易的に行えてしまうという事でとりあえず理解してけばいいかもしれないですね。

参照渡しをするとポインタ渡しの独特な記述がいらないので、我々のような初心者には扱いやすくなります。

 

 

 

どの渡し方も使い方が違いますので一概にこの渡し方をしておけば問題ない!ということはないので状況によってちゃんと使い分けるようにしていきたいです。

 

それぞれの詳しい話はまた後日にします。

 

それではお疲れ様でした。

 

ぷないしん

備忘録{コンストラクタ編}

こんにちは、ぷないしんです。

 

C++を勉強するにあたって特徴でもあり難関といえばいくつか挙げられますが、やはりクラスなのではないかと思います。

 

そこで今日はコンストラクタの重要性と必要性を今一度確認してみましょう。

 

 

まずは何がコンストラクタになるのかということと、その使い方です。

 

とりあえずよく例に挙げられる車を使ってソースコードを書いてみます。

 

class Car{
    int number;
    void kansuu();
    Car();
};

 Carという名前のクラスを作りnumberという名前の変数とkansuu及び,Carという名前の関数を二つ定義しました。

 

どうもこのクラスにおいてCar()というメンバ関数がコンストラクタになるみたいです。

 

そしてなんとこのクラスでオブジェクトを定義した時にこのコンストラクタというヤツは自動的に呼び出されるというのです。

 

という事はメイン関数で下記の様に記述したとします。

int main()
{
    Car tanakaCar;
}

すると、tanakaCarオブジェクトを生成すると共にコンストラクタが自動的に呼び出されるという事ですね。

 

また、いくらコンストラクタが特別といえど、あくまで関数の一つなので記述方法も関数とほぼ同様でOKですが、戻り値(voidなど)が無いことが重要とのことです。

戻り値は無くても引数は設定できるのでそこは注意しないと駄目ですね。

 

 

初期化したいときの内容の記述ですが、本やサイトによって二つの記述方法がありますのでまたソースコードで書いてみたいと思います。

(ナンバー変数を0で初期化します)

 

①クラス内で記述する方法

class Car{
public:
    int number;
    void kansuu();
    Car(){
        number = 0;
    }
};
 

②クラスの外でスコープ演算子(::)を使いアクセスする方法

class Car{
public:
    int number;
    void kansuu();
    Car()
};
 
Car::Car(){
    number = 0;
}

 

基本的には①のインラインでコンストラクタを実装するのが普通みたいです。

 

 

と使い方はこんな感じでしょうか、重要性や必要性はまた明日確認したいと思います。

ありがとうございました。

初めまして

初めまして、ぷないしんです。

 

リーダーのM0CAN(仮)と一緒にゲームを作っていくことにしました。

 

プロジェクト自体は2020年の10月から進行していましたが、この度ブログを立ち上げましたのでリーダーと一緒に更新していきます。

 

ゲームの内容はまだ公開できませんが今年の夏に簡単なゲームの作成を目標にしていきたいと思っています。

 

私は今までまったくプログラムなどやっていませんでしたが、リーダーの元で現在勉強中です。

 

それではこれからよろしくお願いします。

 

ぷないしん