読みやすさは(参照)パラメーターでconstを使用しない正当な理由ですか?


24

いくつかの関数を作成するときに、次のようなパラメーターにconstキーワードが見つかりました。

void MyClass::myFunction(const MyObject& obj,const string& s1,const string& s2,const string& s3){
}

IDEまたはvimで行を2行に分割することがよくあるので、パラメーターのすべてのconstキーワードを削除したいと思います。

void MyClass::myFunction(MyObject& obj,string& s1,string& s2,string& s3){
} 

それはconstを使用しない正当な理由ですか?パラメータオブジェクトを手動で変更しないで維持することはできますか?


110
「ちょっと、プログラムを機能的に変更したい」と読みやすくするのは悪い悪い理由です。
ピーターB

37
プログラムはとにかく読みやすいものでconstはありません。関数内でどのように変更されるかを気にする必要がないという強力なヒントがあるので、渡されたものを見たら。
トフロ

43
読みやすさを改善するより良い方法は、引数の数減らすことです。
5gon12eder

15
'const'は間違いなく読みやすさを改善します。このステートメントは、objが変更されないことを明確にします!
チャールズ

14
読みやすくするには、各コンマの後にスペースを追加します。
サムホセバル

回答:


182

読みやすさは、空白の使用方法を学ぶ正当な理由です。

void MyClass::myFunction(
        const MyObject& obj,
        const string& s1,
        const string& s2,
        const string& s3
) {
    return;
}

そこにあるパラメータは、関数の本体と混同されません。名前を別の行に配置することにより、名前をmyFunctionよりわかりやすい名前に変更するときに位置を変更する必要がなくなります。パラメーターが変更されていない場合にパラメーターの位置を変更しないことは、ソース管理diffツールのユーザーが喜ぶものです。

const何かを意味します。スペースやアイデアが不足しているからといって捨てないでください。可読性は王様ですが、その名のとおりに物事を壊すことはあきらめます。


6
「myFunctionの名前を変更するときに、それらの位置を変更する必要はありません」-この場合、それらは開口部とほぼ並ぶように配置されているように見え(ますが、その場合は再配置する必要がありますクラス+関数名の長さが約4文字を超えて変化する場合にそれらを使用します。したがって、その必要がない場合は、関数名の長さに依存する数ではなく、固定数のレベルのインデントを追加します。私はこの答えは6を使用していますが、任意の固定数が定められた目標を達成:-)、1つのレベルをお勧めします
スティーブ・ジェソップ

6
@CandiedOrangeこの回答で「フォーム6」を使用しなかったことに驚いています... 明らかに clearlyさが減りました!
svidgen

6
勝利のためのフォーム6。1レベルのインデントに対して1つのタブスペース。シンプルで効果的。問題解決:)
モニカとの明るさのレース

2
はい、フォーム6です。これは、JeffGriggがc2で言及したバリアントです。
candied_orange

4
@ random832私たちは今、自転車置き場にしっかりと入っていると思います。これを解決する適切な方法は次のとおりです。例についてコードベースを検索し、ショップのスタイルガイドを参照し、ショップの開発者に尋ねます。信頼できる答えが得られない場合はこれを使用します。4分の1でどちらかの方向に進む可能性のある紛争を解決します。四半期が話されたら、一貫してください!
candied_orange

52

実際、読みやすさの問題は間違いなく別の方向に向かっています。最初に、whitespaceを使用して、実行中の行を簡単に解決できます。ただし、削除constすると行が短くなるだけでなく、プログラムの意味が完全に変わります。

ハーブサッターは、へのconst参照が一時的なものにバインドし、その寿命を延ばすことができるため、参照を最も重要なものconstとして参照します。非値への左辺値参照には、別の変数が必要です。constconstconst

void foo_const(std::string const& );
void foo_nc(std::string& );

std::string some_getter();

foo_const(some_getter());      // OK
foo_const("Hello there"); // OK

foo_nc(some_getter()); // error
foo_nc("Nope");   // error

std::string x = some_getter(); // have to do this
foo_nc(x);                     // ok
std::string msg = "Really??";  // and this
foo_nc(msg);                   // ok

これがユーザビリティにとって意味することは、関数を呼び出すためだけにこれらすべての一時変数を導入する必要があるということです。これらの変数は無意味であり、署名が間違っているためにのみ存在するため、これは読みやすさにはあまり適していません。


6
あなたの2番目の段落は私がどうかを把握しようと頭痛与えconstに参照のうえれるconstか、他にconstどのようなconst実際に最も重要であるconst
Mindwin

3
@Mindwin皮肉なことに、私の2番目の段落は明確で明確であり、あなたが何について話しているのかわかりません。
バリー

2
@Barryそれは確かに明白ですが、それが何を意味するかを理解しようとするために、私はその段落のいくつかの読み取りを取りました。問題のいくつかは、「Herb Sutterがconst(constを参照)を最も重要なconstとして参照している」または「Herb Sutterがconst in(constを参照)を参照している」と解析できることだと思います重要な定数...」後者は単語の唯一の有効なグループ化であると思いますが、それを処理するには少し時間がかかります。たぶん、引用符を使用してあいまいさを取り除く方法がありますか?
コートアンモン-復帰モニカ

1
いくつかのハイフン化された化合物はこれをクリアすると思います。
shawnt00

2
または、そこに名詞(const&const
フレーズ

21

簡単な答えは「いいえ」です。

長い答えは、constキーワードは関数が提供する契約の一部であるということです。引数が変更されないことがわかります。constその保証を削除すると、ウィンドウの外に出ます。ドキュメンテーション、規約、またはガイドラインを使用して、何かの整合性(または他のプロパティ)を合理的に維持できないことを忘れないでください-コンパイラーによって制約が強制されていない場合、誰かがいじって作業を簡単にできる思うでしょうパラメータ「ほんの少し」。考慮してください:

// parameter "foo" is not modified
void fna(Foo& foo);

void fnb(const Foo& foo);

後者のバージョンはより簡潔であるという事実とは別に、より強力なコントラクトを提供し、コンパイラーが意図を維持できるようにします。前者はfna(Foo&)、渡されたパラメーターが関数によって変更されるのを防ぐために何もしません。

@CandiedOrangeの回答のように、空白を使用してコードをレイアウトし、読みやすくすることができます。


14

constキーワードを削除するconstと、リーダーとコンパイラーに情報が伝達されるため、可読性が低下します。
コードの水平方向の長さを短くすることは良いことです(横にスクロールするのが好きな人はいません)がconst、テキスト以上のものがあります。あなたはそれを書き直すことができます:

typedef string str;
typedef MyObject MObj;
void MyClass::myFunction(const MObj& o,const str& s1,const str& s2,const str& s3)

契約は変更されませんが、ラインの長さを短くする必要があります。本当に私が読みにくくなるために、上記のスニペットを検討すると、すでにCandiedOrangeの答えで述べたように多くの空白を使用してを選ぶでしょう。

constコード自体の機能です。関数を非メンバーにしMyClass::て宣言のセクションを削除しないので、削除しないでくださいconst


4
提供するスニペットが読みにくいことに同意します。読者に何が何であるかMObjを調べstrさせ、確かに眉をひそめます。これは、名前がすでにを管理しているタイプのために特に奇妙だ:例:なぜあなたは名前だけではなかったMyObjectようMObjで開始しますか?
ジェイソンC

3

可読性は、パラメーターでconstを使用しない正当な理由ですか?

いいえ。省略するとconst機能が変更され、保護が失われ、const効率の低いコードが作成される可能性があります。

パラメータオブジェクトを手動で変更しないで維持することはできますか?

コードを手動でフォーマットするのに時間費やすのではなく

void MyClass::myFunction(const MyObject& obj,const string& s1,const string& s2,const string& s3){
  //
}

自動フォーマットツールを使用します。機能要件ごとに関数を記述し、自動フォーマットでプレゼンテーションを処理します。手動でフォーマットを調整することは、自動フォーマットを使用し、保存した時間を使用してコードの他の側面を改善するほど効率的ではありません。

void MyClass::myFunction(const MyObject& obj, const string& s1, const string& s2, 
    const string& s3) {
  // 
}

-1

可能な限りconstを表示したままにしておくことをお勧めします。コードのメンテナンスを大幅に改善します(このメソッドが引数を変更するかどうかを推測する必要はありません)。

メソッドに多くの引数が表示される場合、プロジェクトベースのジャロン(Matrix、Employee、Rectangle、Account)の作成を検討するように強制されます。


同意した。指摘するのをためらいました。したがって、「極端なケース」。
ブラックペン

@cmasterそれは、特定のコンテキストでは、特定のプログラマーによっては、読みやすくなる可能性があるということです。たとえば、Windows API呼び出しで非常に特殊なプログラムで、その環境に慣れている読者がいる場合、たとえばtypedef Point * LPPOINTやなどのようなものtypedef const Point * LPCPOINTは、非常に不愉快でありながら、それは当面の期待と一致するため、依然として暗黙の意味を持ちますコンテキストで。しかし、一般的なケースでは決してありません。それは私が考えることができる奇妙な例外です。
ジェイソンC

1
はい、質問を見たとき、「const unsigned long long int」が思い浮かびましたが、「const」または「reference」のいずれかから利益を得ることは良い候補ではありません。typedefは、名前を短縮するという一般的な問題を解決します。しかし、その背後に言語構造(「const」など)の目的を隠すことは、良いデザインのようには感じません。
ブラックペン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.