悪いことを保証するものではありません。ただし、この特定のケースでは不要です。
多くの (またはほとんどの) コンテキストでは、参照は変装したポインターとして実装されます。あなたの例はたまたまそれらのケースの1つです。関数がインライン化されないと仮定すると、パラメーターb
は「内部で」ポインターとして実装されます。setA
したがって、最初のバージョンで実際に渡すのは へのポインタint
、つまり引数値への間接アクセスを提供するものです。2 番目のバージョンでは、immediate を渡します。int
つまり、引数値への直接アクセスを提供するものです。
どちらが優れていて、どちらが劣っていますか? 多くの場合、ポインターは よりもサイズが大きいためint
、最初のバリアントがより多くのデータを渡す可能性があります。これは「悪い」と見なされるかもしれませんが、通常、両方のデータ型がハードウェアのワード サイズに収まるため、特にパラメータが CPU レジスタで渡される場合は、おそらく大きな違いはありません。
また、関数内を読み取るb
には、その偽装ポインターを逆参照する必要があります。これは、パフォーマンスの観点からも「悪い」ことです。
これらは、小さなサイズ (ポインタ サイズ以下) のパラメータを値で渡すことを好む正式な理由です。パラメーターまたはより大きなサイズの場合、const 参照で渡す方が適切です (明示的にコピーを必要としない場合)。
ただし、ほとんどの場合、単純な関数はおそらくインライン化されるため、使用するパラメーターの型に関係なく、2 つのバリアントの違いが完全になくなります。
const
2 番目のバリアントで不要であるという問題は、別の話です。最初のバリアントでconst
は、2 つの重要な目的を果たします。
1) パラメータ値を変更できないようにするため、実際の引数が変更されないように保護します。参照が でなかった場合はconst
、参照パラメーターを変更して、引数を変更することができます。
2) call のように、右辺値を引数として使用できますsome_obj.setA(5)
。それがなければ、そのconst
ような呼び出しは不可能です。
2 番目のバージョンでは、これはどちらも問題ではありません。パラメータはその引数のローカルコピーであるため、実際の引数を変更から保護する必要はありません。パラメータに何をしても、実際の引数は変更されません。SetA
また、パラメーターが宣言されているかどうかに関係なく、既に右辺値を引数として使用できますconst
。
このため、人々は通常const
、値によって渡されるパラメーターにトップレベルの修飾子を使用しません。ただし、それを宣言すると、関数内const
のローカルを変更できなくなりb
ます。適度に人気のある「元のパラメーター値を変更しない」という規則を強制するため、実際にそれを好む人もいます。そのためconst
、パラメーター宣言でトップレベルの修飾子が使用されていることがあります。