topazの遊び場

いろいろやってみる

そろそろC++やるぞパート3 関数

そろそろC++やります

そろそろC++をやります。そろそろC++をやりたいからです。
何回やるかはわかりません。基礎を理解するまではやろうと思います。

という感じでやっています。

※ 初心者がメモレベルで記録するので、技術記事としてはお力になれないかもしれません。

内容

基本的な関数

  • 一般的な操作を 1 つの再利用可能なブロックでカプセル化するのに役立ちます。
  • プログラム内の任意の数の場所から起動する、もしくは呼び出すことができます。
int sum(int a, int b)
{
    return a + b;
}
int main()
{
    int s = sum(10, 47);
    cout << s << endl;
    return 0;
}

関数宣言部分

ヘッダーファイルの作成などがあり、関数の宣言関数の実態を別に記載することができます。

int sum(int a, int b);

最小限の関数宣言は以下の要素で構成されます。

  • 戻り値の型
  • 関数名
  • パラメーターリスト (空も可)

戻り値の型 : 関数が返す値の型, 値が返されない場合はvoid, コンパイラ型推論するautoが指定できます.

void CoutIntLn(int v);
auto sum(int a, int b);

関数名 : 文字またはアンダースコアで始まる必要があります。

void hello();
void Hello();
void _hello();

パラメーターリスト : 0個以上のパラメータリストで、型とローカル名を指定します。

void hello();
void hello(int a);
void hello(int a, int b);
関数宣言の省略可能な部分

こちらはそろそろC++をやるパート3では早い内容なので、キーワードだけ残して必要時にまとめることとします。(参照

constexpr, extern, inline, noexcept, const, volatile, override, final

関数定義

宣言と関数本体で構成され、中かっこで囲まれています。 これには、変数宣言、ステートメント、および式が含まれます。 (変数宣言やステートメント、式について詳しくはのちのちやります。)

  • int value {i};int型valueという変数の宣言
  • if は選択ステートメント
  • != を含む部分は式

ソースコード元

int foo(int i, std::string s)
{
   int value {i};
   MyClass mc;
   if(strcmp(s, "default") != 0)
   {
        value = mc.do_something(i);
   }
   return value;
}

関数の{ }の中で宣言された変数は、ローカル変数ローカルと呼ばれます。
こちらに記載されていた、「これらは関数の終了時にスコープ外に出るため、関数がローカルに参照を返すことはありません。」について、「ローカルに参照を返す」が理解できませんでしたが、スコープを外れたら、定義したローカルへの参照がなくなる、ということだと思います。

関数テンプレート

テンプレートの概念が分からなかったため読んでも理解できませんでした。
テンプレートの項目を行った後に、また読んでみます。

関数のパラメータと引数

関数には、0個以上の、型と名前を持ったパラメータのリストがあります。
呼び出し元では引数を渡します。

規定では、引数は関数に値渡しで渡されます。つまり、コピーを渡します。

void swap(int a, int b)
{
    int tmp = a;
    a = b;
    b = tmp;
}
int main()
{
    int a = 10;
    int b = 30;
    cout << a << " , " << b << endl;
    // Output: 10 , 30
    swap(a, b);
    cout << a << " , " << b << endl;
    // Output: 10 , 30
    return 0;
}

パラメーターに参照の量指定子(&)を追加することで、 参照渡し (具体的には左辺値参照) にできます。

void swap(int &a, int &b)
{
    int tmp = a;
    a = b;
    b = tmp;
}

int main()
{
    int a = 10;
    int b = 30;
    cout << a << " , " << b << endl;
    // Output: 10 , 30
    swap(a, b);
    cout << a << " , " << b << endl;
    // Output: 30 , 10
    return 0;
}

引数を変更しないようにするには、パラメーターを & として修飾します。 日本語は間違えていた。
To prevent a function from modifying such an argument, qualify the parameter as const&: 英語版
constと&をつけると参照渡しにしますが、引数を直接変更できないようにします。

void swap(const int &a, int &b)
{
    int tmp = a;
    a = b;
    // error: cannot assign to variable 'a' with const-qualified type 'const int &
    // (エラー: constがついてる変数`a`に代入することはできません。)
    b = tmp;
}

右辺値参照または左辺値参照の引数を明示的に処理するには、パラメーターで二重アンパサンドを使用して、ユニバーサル参照を示します。
こちらも 右辺値参照、左辺値参照、ユニバーサル参照を理解しきれていないので後回しにします。

void DoSomething(const std::string&& input){...}

void 一つのキーワードのみの関数を作ることができ、この場合引数を受け取ることができません。

// OK same as GetTickCount()
long GetTickCount( void );

ここで説明する場合を除き、引数を void 指定することは無効です。
他にも用途があるみたいだが、型など他の機能を知ってから確認します。

規定の引数

関数の最後のパラメータに規定の引数を割り振ることができます。
呼び出す元で省略することができます。

void coutInt(int a1, int a2, int a3 = 10)
{
    cout << a1 << " , " << a2 << " , " << a3 << endl;
}

int main()
{
    coutInt(1, 5, 12);
    // Output: 1 , 5 , 12
    coutInt(2, 7);
    // Output: 2, 7 , 10
    return 0;
}

最後のパラメーターにと書いてあるが、実際には最後だけではなく、最後から連なる複数のパラメータに規定の引数を振りわてることができる。

void coutInt(int a1, int a2, int a3 = 10)
{
    cout << a1 << " , " << a2 << " , " << a3 << endl;
}

int main()
{
    coutInt(1, 5, 12);
    // Output: 1 , 5 , 12 , 14
    coutInt(2, 7);
    // Output: 2, 7 , 10 , 14
    return 0;
}

最後から連なる規定の引数なので、途中だけ規定の引数が入っているのはいけません。

void coutInt(int a1, int a2, int a3 = 10, int a4)
// error: missing default argument on parameter 'a4'

これ以降

これ以降は型、テンプレート、クラス、構造体、ポインターと、まだ扱っていない内容が多いので、今回はここまでとします。

参考サイト

感想

基本的な構造は、真新しいものはなく、読める形の書き方でした。ただ、関数はプログラムでは欠かせない部分で、他の様々な機能と関係が深く現時点では理解しきれない部分が多いなと感じました。

次回はクラスに入りたいと思います!