CRのブログ

音楽とかPCまわりのことを中心に

出力の参照渡しとポインタ渡しの比較

概要

関数の引数はGoogle C++ Style Guideに従って以下の形式にすると良い.

void myclass::hoge(const myclass& a,
          int val,
          int* answer1,
          int* answer2);
  • 入力については,ポインタ or const参照
  • 出力は必ずポインタで渡す
    • 出力先としてnullptrを指定して,要らない出力は受け取らないみたいなことが出来る.

はじめに

最近C++を始め,Effective C++C++のためのAPIデザインなどを読みながら勉強しています.

コーディング規約としてはGoogle C++ Style Guideを参考にしているのですが,参照引数について規約の理由を検討しました.

結果,エラー処理の考え方によってはリーズナブルだと分かりました. (なお,例外は使わない方針です -> Google C++ Style Guide)

参照引数に関する規約の概要

参照引数の箇所によると以下の方針.

  • const参照は効率的だから使う.
  • 入力引数のポインタ渡しは,nullptrを渡したい場合に使う.
  • 非const参照は,通常の引数と違って値が書き変わるのが分かりにくいため使わない.
    • 出力引数として参照を使用してはいけない.ポインタを使う.

出力の参照渡しの利点

入力をconst参照で渡すのは効率的でよい.これはEffective C++にも書いてあります. ただ,出力をポインタで渡すと,nullptrチェックが必要になります.

例えば,以下のような関数を考えます.

void getValuesByPointer(int* x, int* y)
{
    if (x != nullptr){
        *x = 1;
    }

    if (y != nullptr){
        *y = 2;
    }
    return;
}

参照ではnullptrになりえないので,チェックは不要です.もっと簡潔に書けます.

void getValuesByRef(int& x, int& y)
{
    x = 1;
    y = 2;
    return;
}

出力のポインタ渡しの利点

出力をポインタで渡すと,明示的に受け取らないということが可能になります. 上の例でxだけ取得したい場合,参照を使ったコードでは以下のようになります.yは宣言しているのに使いません.

int main()
{
    int x;
    int y; // 不要だけど宣言しないとダメ
    getValuesByRef(x, y);
    cout << x << endl;
    return 0;
}

一方ポインタでは以下のように書けます.

int main()
{
    int x;
    getValuesByPointer(&x, nullptr);
    cout << x << endl;
    return 0;
}

これはちょうどPython_みたいな感じです.参照と比べて非常に便利. また,intではなくて非常に大きなオブジェクトの場合は,メモリサイズ削減にも寄与します.

まとめ

出力はポインタで渡す設計にしよう.