いくつかのサイトで「非constな参照を使うと、コードがわかりにくくなるから使わないほうがよい。参照はconstにすべし。間接的に値を変更したいのであれば、参照ではなくポインタを使ったほうがよい」というようなことが書かれていました。
自分には、参照もポインタも同じようなものにみえます。
非constな参照は、本当に使わないほうがよいのでしょうか??
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答7件
0
ベストアンサー
非constな参照は、本当に使わないほうがよいのでしょうか??
特定の文脈を指しているか分からなかったので、大まかなガイドラインを提示してみます。いずれも C++ Core Guidelines をベースとしています。(あくまでガイドラインの一つですから、個人/プロジェクト/開発組織の事情で調整ください。)
- ローカル変数型:**デフォルトで「const参照型」**を検討しつつ、オブジェクトを変更するケースでは非const参照型を利用します。例:範囲for文での
for (const auto& e: c)
/for (auto&& e: c)
など。 - 関数の引数型:**デフォルトで「const参照型」**を検討をすべきです。“In-Out引数”のように用いるケースでは「非const参照型」が使えるかもしれません。"引数無し"もとりうるケースでは「ポインタ型」を、型サイズが小さい場合は「値型(
T
)」も検討ください。 - 関数の戻り値型:参照型の場合は戻り値オブジェクトの生存期間(lifetime)と所有権(ownership)について十分注意する必要があります。メンバ関数で
*this
参照を返す場合は、const/非constは動作セマンティクスに合わせて選択します。 - クラスのメンバ変数型:参照型よりも値型(
T
)やスマートポインタ(shared_ptr<T>
,unique_ptr<T>
)を検討すべきです。オブジェクトの生存期間(lifetime)と所有権(ownership)について十分注意する必要があります。
関連するガイドライン項目:
- I.11: Never transfer ownership by a raw pointer (
T*
) or reference (T&
) - F.16: For "in" parameters, pass cheaply-copied types by value and others by reference to const
- F.17: For "in-out" parameters, pass by reference to non-const
- F.43: Never (directly or indirectly) return a pointer or a reference to a local object
- F.44: Return a
T&
when copy is undesirable and "returning no object" isn't needed - F.60: Prefer
T*
overT&
when "no argument" is a valid option - C.32: If a class has a raw pointer (
T*
) or reference (T&
), consider whether it might be owning - C.145: Access polymorphic objects through pointers and references
- R.4: A raw reference (a
T&
) is non-owning - R.37: Do not pass a pointer or reference obtained from an aliased smart pointer
- CP.31: Pass small amounts of data between threads by value, rather than by reference or pointer
- Con.3: By default, pass pointers and references to
const
s
投稿2019/09/02 04:03
総合スコア6191
0
こんにちは。
自分には、参照もポインタも同じようなものにみえます。
私も「同じようなもの」として捉えています。そして、参照はポインタの機能制限版です。
制限された機能で十分なケースでは制限されていた方がデバッグが捗ります。
int* foo;
とint& foo;
は似たような機能を提供してくれます。
最大の相違点は前者はnullptrで容易に初期化できますが、後者はかなり変な記述をしないとできません。(そもそも未定義動作を引き起こしますし。)
ですので、私は可能な時は後者を使います。これにより、間違ってnullptrを渡すようなコードを事実上かけなくなりますので、デバッグの時にそれを疑う必要がなくなり開発が捗ります。
投稿2019/09/01 09:47
総合スコア23274
0
まあ宗教戦争ではありますが、個人的にはポインタは使うべきではないと考えます。
ポインタを引数に使った瞬間、その関数でNULLチェックをする義務が生じます。でももしNULLだった場合どうやって呼び出し側に通知しましょうか?例外だと実行コストが重すぎですね、std::optionalのようななにかだとエラー内容が伝わりません。std::error_codeを返すのも手ですがだいぶ面倒くさいです。
仮にこうしてどうにかエラー通知を組んでも、例外以外では呼び出し側でNULLを渡してたらどうするという処理を書かないといけませんね、めんdです。
と考えていくと、そもそもNULLチェックの責任は関数の呼び出し側にあるべきです。これを要求できるのが参照を使う強みです。
投稿2019/09/02 00:41
総合スコア5852
0
「一方のみを使って,他方を忌避した方がよい」という宗教じみた考え方は違う感.
性質が異なる物が2種類存在するのなら,やりたいことに適する方を使う(使い分け).
void F( XXX &rXXX ); //引数が参照
という関数があるとしたら,それは
「引数には,真っ当に生成されたオブジェクトを渡せ.当該オブジェクトは関数内で変更され得る」
ということを表現しているのであり,
void F( XXX *pXXX ); //引数がポインタ
という関数があるとしたら,それは
「引数がオブジェクトを指す場合には,当該オブジェクトは関数内で変更され得る.引数にnullptrを渡した場合にどうなるのか?に関してはリファレンスなり注釈なりでしっかりと確認されたい」
ということを表現しているのだと考えます.
投稿2019/09/02 03:43
総合スコア12151
0
C言語を主にやっていた人からするとインスタンスを引数に指定したときぱっと見では参照渡しが行われたのか値渡しによりインスタンスのコピーが行われたのか分かりにくいからだと思います。
ポインタであればインスタンスのコピーは発生しないのでそれだけで安心です。
自分が設計する場合は参照渡しを使うのはoperatorの実装で必要な時のみでそれ以外の関数であればconstだろうが非constだろうがポインタ指定にします。
投稿2019/09/01 08:50
総合スコア1627
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/09/02 05:35