C ++での非オプションポインターと非const参照


12

では他のC ++の機能、リファレンス引数GoogleのC ++スタイルガイドでは、私は非const参照は使用してはならないことをお読みください。

参照によって渡されるすべてのパラメーターには、constというラベルを付ける必要があります。

引数として参照を使用する関数呼び出しを見ることは、Cプログラマーにとって完全に混乱することは明らかですが、CとC ++は今では異なる言語です。出力パラメーターが必要な場合、必要な出力パラメーターへのポインターを使用すると、関数本体全体がスキップされる可能性があり、関数の実装がより複雑になります(関数の循環的な複雑さ深さが正式に増加します)。

C ++コードをできるだけ簡単に理解/保守できるようにしたいので、コーディングスタイルガイドを読むことに興味があります。しかし、チームのベストプラクティスを適応させるには、スタイルガイド要素の背後にある理論的根拠を理解することが重要な要素だと思います。

非const参照は本当に悪いですか?それらを禁止するのはGoogle固有のものだけですか、それとも一般に受け入れられているルールですか?出力パラメーターをポインターとして実装するための余分な労力を正当化するものは何ですか?


2
「ポインタを使用すると、関数本体全体がスキップされます」
ラチェットフリーク

@ratchetfreakこれを明確にしようとしました。このような機能にはいくつかの設計上の欠陥があることを認めます。ポインターは常に正式なオプションであるため、逆参照する前にチェックする必要があります。
ウルフ

4
GoogleのC ++スタイルガイドはかなり後向きです。私の主観的な意見では、それは燃やされるべきです。
Siyuanレン

この特定の項目に関しては、引数が変更される可能性がある場合にプログラマーにアンパサンドを書くように強制すると、より明確な意図が示されると考えています。
Siyuanレン

4
Googleスタイルガイドは、Googleのレガシープロジェクトで同種のコードをサポートするために、そのまま作成されました。(最初からこのスタイルガイドで書かれた)レガシープロジェクトで作業していない場合は、おそらく使用しないでください(新しいコード(c ++ 11、c ++ 14 、c ++ 17)))。
utnapistim

回答:


18

Googleのスタイルガイドの背後にある論理的根拠は、単にパラメーターが入力パラメーターであるか出力パラメーターであるかを関数の呼び出しサイトから明確にすることです。(詳細については、こちらを参照してください。)他の言語では、設計によりパラメーターが明示されています。たとえば、C#には、呼び出しサイトで使用outする必要があるキーワードがあります。C ++では明示的にされていないため、Googleはconst refの使用を選択しました。明確にするためのポインタ。

これは単なるGoogleのルールですか?いいえ、しかし、私はそれが非常に広まっているとは思いません。Googleのスタイルガイドや、Googleスタイルガイドの一部を明示的に遵守しているグループ以外では見たことがないと思います。(たとえば、私が何年も前にGoogleスタイルガイドを最初に読んで、自分のコードのいくつかにそれを使用したとき、私はこのアイデアが好きでした。

特に、新しく発表されたC ++コアガイドラインは、(ほぼ)すべての出力パラメーターに戻り値を優先し、残りには非const参照を使用します。Googleがポインターと参照を使用すると、出力パラメーターがより明確になりますが、戻り値はより明確になります。C ++ 11には標準化された移動(&&多くの型の戻り値を安くするための右辺値参照、)およびタプル(複数の値を簡単に返す方法を許可する)があるため、出力パラメーターのユースケースの多くは適用されなくなりました。

C ++コアガイドラインにはいくつかのビッグネーム(Bjarne Stroustrup、Herb Sutter)があり、Microsoftによってサポートされており、最新のC ++機能(Googleのスタイルガイドとは異なります)を採用しているため、Googleの推奨事項よりもGoogleの推奨事項の方が人気があると思います。


答えてくれてありがとう(C#への短い遠足も)。もちろん、特にオープンソースプロジェクトでは、簡単なレビューは重要なポイントです。最新のC ++で安価なリターンを得ると、これらの考慮事項は重要性を失います。古いレガシソフトウェアと古いコンパイラを使用している場合は、引き続き役立つ場合があります。
ウルフ

私はそれを忘れていませんでしたが、C ++コアガイドラインはすぐに入手できません。コミュニケーションの方法として、その哲学がルールの背後にある理論的根拠と、プログラミングに関する最新の見解(「コードで直接アイデアを表現する」がPythonのZenに少し似ている)を示しているのは興味深いことです。
ウルフ

補足:C ++コードガイドラインの哲学セクションへの直接リンク。
ウルフ

1

渡された無効なポインターを処理するための2つのオプションがあります。最初のチェックとアーリーリターン、または未定義の動作(堅牢性よりも速度を重視する場合)です。

チェックは次のように簡単です。

void foo(void* buffer){
    if(buffer == nullptr)
        return;

    //actually foo

    // note no increase in indentation required

}

このタイプのチェックは、一般的にパラメーターチェックとして受け入れられます。コードを見ると、null以外のポインターが渡され、そうでない場合は早く戻ることが予想されることは明らかです。これにより、無効なポインターについてそれほど心配する必要がなくなります。


まあ、私はこのパターンについて考え、それが絶対に合理的であると思います。悲しいことにassert(buffer);、アサートはデバッグバージョンに対してのみアクティブであることを知っているので、明確ではないように見えますrt_assert(buffer);が、例外をスローするようにしたいことがあります。のインデントはreturn少し危険に見えます...ところで:あなたのコードスニペットは、出力のポインターに関する私の質問の良い例です。
ウルフ

1

それはあなたの観察にかかっていますIf an output parameter is required

関数シグネチャが出力パラメーターを持つために必要な唯一の場所は、外部APIによって指定された場合であり、そのような場合、常に有効な指示先が存在することを保証するもので外部APIをラップします。

内部的には、戻り値の型をすべての「出力」の複合になるように拡張することにより、出力パラメーターを回避します


つまり、必須ではないポインタを提供できない唯一の場所ですか?確かに、あなたのルールThe only place where...が本当にすべてのケースに適用されるかどうかはわかりません。あなたが提案するものは次のように見えます:あなた自身のプログラムの機能で出力パラメータを避けてください。新しいプログラムに当てはまります。
ウルフ

1
はい、出力パラメーターを避け、複合戻りタイプを優先し、より明確にするために編集しました
-Caleth
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.