アトリエ ぺっぺ

トップページ > プログラムTips > ポインタのアウト引数

◆ ポインタのアウト引数
C++になって参照引数が使えるようになりました。
では、今まで引数にポインタを使っていたような場面を、全て参照にしてしまった方がいいのでしょうか?

例えば、こんな関数があったとします。
void getCurTime(int& nYear, int& nMonth, int& nDay,
                int& hh,    int& mm,     int& ss)
{
    CTime time = CTime::GetCurrentTime();
    nYear = time.GetYear();
    nMonth = time.GetMonth();
    nDay =  time.GetDay();
    hh = time.GetHour();
    mm = time.GetMinute();
    ss = time.GetSecond();
}
現在の日時、時間を返してくれる関数ですね。
しかし、この関数だと、もし現在の『日付だけ』が欲しい場合にも、下のように変数を6つ用意しなければなりません。
void main(){
    int nYear, nMonth, nDay, hh, mm, ss;
    getCurTime(nYear, nMonth, nDay, hh, mm, ss);
    printf("本日は%0000d年%00d月%00d日です");
    // hh, mm, ssは使っていない!!
}
まぁこれでも問題ない場合も多いのですが(笑)、沢山の使わない変数を用意しなければならないというのは、あまり気分のいいものではありませんね。
そこで、以下のように関数を変えてみてはどうでしょうか。
// ポインタがNULLじゃなければ代入、のマクロ
#define SAFE_SET(p, val)   (if(p) *p = val)

void getCurTime(int* nYear,     int* nMonth = NULL, int* nDay = NULL,
                int* hh = NULL, int* mm = NULL,     int* ss = NULL)
{
    CTime time = CTime::GetCurrentTime();
    SAFE_SET(nYear, time.GetYear());
    SAFE_SET(nMonth, time.GetMonth());
    SAFE_SET(nDay, time.GetDay());
    SAFE_SET(hh, time.GetHour());
    SAFE_SET(mm, time.GetMinute());
    SAFE_SET(ss, time.GetSecond());
}
こうすることにより、先ほどのmainは次のように書くことができます。
void main(){
    int nYear, nMonth, nDay;
    getCurTime(&nYear, &nMonth, &nDay);
    printf("本日は%0000d年%00d月%00d日です");
}
どうでしょう。
無駄な変数を定義する必要がなく、すっきり感じた方も多いのではないでしょうか。
これも好みの問題になってしまうので、もししっくりこない方は、『こんな方法もある』程度に心にとどめておいてください。


この「必要な場合とそうでない場合がある引数」にポインタを持ってくる方法は、引数にクラス等のサイズが大きめのモノが来る場合、インスタンスそのものをデフォルト引数に使う方法に比べ、メモリの無駄遣いを少なくするという効果もあります。
しかし、あくまでもポインタなので、多用するか否かはプログラマのセンスにかかってくると思います。


大容量時代を迎えた今、「よいプログラム」とは、効率はもちろんのこと、保守に多大に関わる『可読性』も重要なファクターとなってきます。
効率と可読性、一番いいバランスを保てるように、コーディングしていくことに心がけていきましょう。


(C) 2002 atelier-peppe
ababa@atelier-peppe.sakura.ne.jp