C++プログラマーの方に質問です。const の参照引数を使う事はよくありますが、非const の参照引数を使うのは避けた方がいいのでしょうか?

void func(T& t) ;
T hoge ;
func(hoge) ;
のように非const の参照引数を使う場合、呼び出し側のソースを見た時に引数として渡す変数は不変だと判断してしまいがちです。
そのような場合はポインタを使用して
void func(T* t) ;
T hoge ;
func(&hoge) ;
とすれば呼び出し側からも一目見るだけで引数として渡した変数が変更される可能性があるとわかります。
ということは非const の参照を引数として使うのは必ず避けた方がいいのでしょうか?
「ポインタと参照の使い分け」
「非constの参照引数」
について解説しているWebページ、もしくは合理的な回答を期待しています。

回答の条件
  • URL必須
  • 1人2回まで
  • 登録:2004/03/25 12:28:15
  • 終了:--

回答(7件)

id:mcq No.1

mcq回答回数62ベストアンサー獲得回数32004/03/25 12:51:39

ポイント80pt

http://www.tietew.jp/cppll/archive/8965

[cppll:8965] メソッドパラメータのポインタ引数と参照引数

このスレッドを見る限り、未だ議論の残る問題のようです。

このページは明確な基準を示しています。

id:osietekun

上のリンクの

>仰るような理由で「const でない参照引数を使うな」と Straustrap が「プログラミング言語 C++ 3rd」で 書いていますね。

というコメントで方向性が決まりました。

ストラウストラップに習ってconst ではない参照引数は使わない事にします。

どうも、参照引数は値渡しの低コスト版であるべきというのが根底にあるような気がしました。

>NULLになり得る場合、ポインタで。

>NULLになり得ない場合、参照で。

これは自分もそうしてましたが、引数での参照型の問題はまた更に深く考えるところがある気がしてます。

2004/03/25 15:33:00
id:yoshimichu No.2

yoshimichu回答回数11ベストアンサー獲得回数02004/03/25 13:12:51

ポイント20pt

URLはダミーです。

私はMacitoshの仕事をよくするために、Macでよく使用される

コンパイラであるCodeWarriorに付属するPowerPlantという

クラスライブラリで使用されている記法を使用しています。

メソッドや関数の引数には、プリフィックスとして

in、out、io

を付けます。

void Func( const T& inValue );

void Func( const T* inValue );

inValueは参照以外に使わない

void Func( T& outValue );

void Func( T* outValue );

outValueに結果を出力する

void Func( T& ioValue );

void Func( T* ioValue );

ioValueは、入力された値を変形してioValueに結果を返す

言語仕様ではなく、ローカルなコーディングルールに依存するので

厳密ではないですが、ポインタでも参照でも対応でき、さらに

言語が変わった場合でもこの記法である程度の対応は可能です。

私はこの方法でかなりのミスを減らせると体感しております。

id:osietekun

ほほう。

これを見て聞きたいポイントは

void Func( T* outValue );

void Func( T* ioValue );

があるなら

void Func( T& outValue );

void Func( T& ioValue );

は要らないんじゃないか?ってとこなのです。

メンバ関数はできるだけ少ない方がいいはずですし。

2004/03/25 15:36:23
id:yoshimichu No.3

yoshimichu回答回数11ベストアンサー獲得回数02004/03/25 13:13:41

URLはダミーです。

私はMacitoshの仕事をよくするために、Macでよく使用される

コンパイラであるCodeWarriorに付属するPowerPlantという

クラスライブラリで使用されている記法を使用しています。

メソッドや関数の引数には、プリフィックスとして

in、out、io

を付けます。

void Func( const T& inValue );

void Func( const T* inValue );

inValueは参照以外に使わない

void Func( T& outValue );

void Func( T* outValue );

outValueに結果を出力する

void Func( T& ioValue );

void Func( T* ioValue );

ioValueは、入力された値を変形してioValueに結果を返す

言語仕様ではなく、ローカルなコーディングルールに依存するので

厳密ではないですが、ポインタでも参照でも対応でき、さらに

言語が変わった場合でもこの記法である程度の対応は可能です。

私はこの方法でかなりのミスを減らせると体感しております。

id:osietekun

あれあれ?

さっきの回答と一緒です。

2004/03/25 15:36:52
id:aki73ix No.4

aki73ix回答回数5224ベストアンサー獲得回数272004/03/25 13:15:05

http://winfaq.jp/

Windows.FAQ - ウィンドウズ処方箋

単独で使うならその方が無難ですね

ただ、渡す引数の方がConstだと決まってるなら、間違って非Constを渡したときに警告が

コンパイル時に出ますから、間違いを防止するという意味では有用です

同じ関数名で、Constの引数のもの、そうでないものを混在すると、別の関数として扱われるコンパイラもあるし、constで定義しても、キャストすればコンパイル通りますし、要は、利用する側の使い分けですね(^^;

id:osietekun

よくわかりません。

>渡す引数の方がConstだと決まってるなら、

「渡す引数」が仮引数のことなら、

仮引数がconstで実引数が非constでも警告は出ないですよね?

「渡す引数」が実引数のことなら、

仮引数が非constで実引数がconstなら警告じゃなくてエラーがでますよね?

2004/03/25 15:48:53
id:kobayakawa No.5

kobayakawa回答回数13ベストアンサー獲得回数02004/03/25 13:37:56

http://www.hatena.ne.jp/1080185295#

C++プログラマーの方に質問です。const の参照引数を使う事はよくありますが、非const の参照引数を使うのは避けた方がいいのでしょうか? void func(T& t) ; T hoge ; fun.. - 人力検索はてな

例によってURLはダミーです。

連続したメモリ空間(配列など)にアクセスするかどうかで使い分けています。

渡したオブジェクトが変更されるかどうかを、呼び出し部の記述で判断してしまうこと自体がナンセンスではないでしょうか?せめてシグニチャ位は確認した方がよいのでないでしょうか?

void func(char *str);

char buf[64];

func(buf);

というように記述してしまえばポインタを使用しても変わらないと思いますが・・・?

id:osietekun

>ナンセンスではないでしょうか?

ナンセンスではないと思います。

>せめてシグニチャ位は確認した方がよいのでないでしょうか?

「シグニチャ」の単語の使い方を勘違いしているように見えました。

回答を一言でいうと「配列は参照使えないからポインタ」ってことですよね?

それは質問内容とだいぶ乖離した回答だと思いました。

2004/03/25 15:54:15
id:disca No.6

disca回答回数26ベストアンサー獲得回数02004/03/25 14:21:54

const ぜひ使うべきだと考えています。

可読性のため(他の方が見た場合すぐわかります)とても重要なことだと思います。

Windowsプログラミングでよく使われる、

LPTSTR、と、LPCTSTR(Const THAR文字列)のように、マイクロソフトも提唱していますから^^。=デファクトスタンダード?

あと、ポインタ渡しは、時にNULLポインタを渡してしまうことによる無効なポインタを指定してしまうことがありますが、参照ですと、そういったことがない為にバグに直接的につながる可能性が少なくなります。また、人間的にソースコードを理解する上で、ポインタ演算より、参照による演算のほうが、理解しやすい=バグの軽減、またプログラムを嫌う方の多くは、ポインタのややこしい概念があるたなどになります。

id:osietekun

const についてだけの質問でもありませんし、参照についてだけの質問でもありません。

const と 参照 と 引数 をからめた場合の質問です。

2004/03/25 15:55:51
id:aki73ix No.7

aki73ix回答回数5224ベストアンサー獲得回数272004/03/29 15:45:52

よくわかりません。

>渡す引数の方がConstだと決まってるなら、

「渡す引数」が仮引数のことなら、

仮引数がconstで実引数が非constでも警告は出ないですよね?

「渡す引数」が実引数のことなら、

仮引数が非constで実引数がconstなら警告じゃなくてエラーがでますよね?

そのとおりです

ですから

void sample(char *fnc);

な関数の場合

const char a[]=”abc”;

sample((char *)a);

とすればエラーにならないです

const にすると、アクセス速度やメモリ領域の節約になりますから、関数で呼び出す側も同じように最適化されます

ですから、混在すると効率性が落ちてよくないですね。

分かっててキャストしてつかうならいいかと思いますが

そもそも機械語レベルではWindows32アプリはどの型も32bitのPush/Popで関数を呼び出してるので、コンパイル時のポインタの扱いが違ったり、直接アドレスを渡したり、使い分けてるんですよね

const にすることによって、書き込みを行ったときにエラーを返させるような仕組みにコンパイラがなってるとか

id:osietekun

よくわかりません。

>const にすると、アクセス速度やメモリ領域の節約>になりますから、関数で呼び出す側も同じように最適化されます

>ですから、混在すると効率性が落ちてよくないですね。

ここから下全て間違ってるように見えます。

有意義な回答なさそうなので終了とします。

2004/03/30 07:51:49
  • id:disca
    ポイント要らないけれど

    ポイントなんて要らないけれど
    こういった質問の終了方法って凹むな(苦笑
    www.whitehouse.gov
  • id:yoshimichu
    補足説明

    2,3に同じ内容を書き込みしてしまった者です。
    補足説明をしたかったのですが、間違えて二度回答してまうと、
    質問が終了するまで自分の意図を伝える手段が無いようですね...


    >これを見て聞きたいポイントは
    >void Func( T* outValue );
    >void Func( T* ioValue );
    >があるなら
    >void Func( T& outValue );
    >void Func( T& ioValue );
    >は要らないんじゃないか?ってとこなのです。
    >メンバ関数はできるだけ少ない方がいいはずですし。

    私の書き方がまずかったのかもしれませんが、Funcはそれぞれ
    表記の例であって、すべて別々の関数もしくはメソッドの宣言
    だと思って下さい。実際には上か下のどちらか一方の形式を
    選んでコーディングすることになると思います。

    私の感覚としては、上よりも下の参照形式を利用した
    ほうがC++的だと思っていますので、可能な限り参照形式を
    利用するようにしています。

    ポインタを利用した場合には、間違ってNULLや、不正なアドレスが
    渡され来る可能性がありますが、参照ならばまず大丈夫です。
    たしかに、呼び出し側のコードを見ただけでは値が変更されるか
    どうかがわからないという問題がありますが、それは呼び出される
    関数やメソッドの宣言をみて、in/out/ioで判断、ということに
    しています。

    わかりにくい説明ですいませんが、参考までに。
  • id:mcq
    Re:補足説明

    >補足説明をしたかったのですが、間違えて二度回答してまうと、
    >質問が終了するまで自分の意図を伝える手段が無いようですね...

    ポイント送信をする際にコメントを付ける事ができるので、1ポイント送信+1ポイント手数料=2ポイントかければ、質問者の方に補足を伝えたり、早期終了をお願いして”いわし”で補足したりする事が出来ます。
    ただし、300ポイント以上無いと送信できません。頑張って早く貯めて下さいね。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません