2016-03-25 1 views
-2

C++で定数値への定数ポインタを使用する理由がありますか? srcディレクトリで誰かが私に与えてくれたので、varに書き込もうとしなくても、値を読み取っただけなので、その背後に理由はありません。データを読み込むときに定数のポインタを使うのはなぜですか?

定数ヴァースの定数ポインタを使用するのは、読んで一度だけ必要な場合でも同じですか?

bool 
serialize_state(int const fd, game_state const * const state) { ... } 

=>定数のgame_stateへの定数ポインタは、保存された「状態」ですか?

+5

*彼らはvarに書き込もうとしません、彼らはちょうどそこから値を読み取る*その事実を知る簡単な方法は何でしょうか?シグネチャでconstを見つけるか、メソッド全体を解析して(そして、すべてのメソッドがそれを順番に渡して)書き込みを行いますか?また、書かれていないので、定数で安全に呼び出すことができます。 –

+0

質問は逆の言い方をしています:データを読み込んだだけの場合はなぜ*読み取り専用タイプを使用しないのですか?あなたは実際に書くときに読み取り専用のタイプを使用することはできませんか? – Angew

答えて

2

constへのポインタは、クライアントが値を変更したりポインタを変更したりすることができないことを保証します。該当する場合、このアプローチは、いくつかの利点があります。あなたがいけないプログラムの一部を変更することは不可能(あるいは少なくとも困難)であることから

  • は、より安全で、よりエラー/バグが発生しやすいです。
  • Joachim Isakssonがコメントで述べたように、関数の引数として使用すると、一定の値を持つ関数を安全に呼び出すことができます(関数はそれらを変更しないことが保証されているので)
  • 一時的にそれらの値
  • それは意図は、コードによる明示的な(というよりもコメントを通じて)になり、特定のエラーはコンパイル時

でキャッチすることができるように、私は本当に実在の欠点を見ることができないので、私からのアドバイス同じconstオブジェクトへの生ポインタを必要とするときは、常にそれらを使用します。つまり、とにかくstd::unique_ptrstd::shared_ptrが標準に含まれているので、私は生ポインタを使用しないようにアドバイスします。

+0

"*プログラムの一部を変更する*あなたは"おそらくタイプミスではありません。 –

+0

"関数の引数として使用すると、一時的な値を渡すことができます"ここではconst型の型参照の正式な引数について話していると思います。 constポインタについて話していない。 ;-) –

+0

Re "本当に不利な点は本当にありません"と言っていますが、一般的には 'const'引数は' move'の禁止です。 –

1

ほとんどの場合、可能な限り変数をconstにするのは、意図を表現し誤用の可能性を減らすための良いものです。

しかし、引数を渡すときには警告があります。

void foo(const char* text);  
void foo(const std::string& text); 

しかしCONSTを作り、引数として実際のコピーを渡す際に多くの欠点を有する:

CONSTリソースへのポインタまたは参照を渡すことによって、賢明かつ正確です。考えてみましょう:

std::string sorted(const std::string source) 
{ 
    // I must copy source again because it's immutable 
    auto result = source; // redundant copy 
    std::sort(std::begin(result), std::end(result)); 
    return result; 
} 

可変引数を渡す一方、機能がより効率的にそれを使用することができます:

std::string sorted(std::string source) 
{ 
    // lots of opportunity for copy elision and RVO here. 
    std::sort(std::begin(source), std::end(source)); 
    return source; 
} 

をこれは良い形であるかどうかの特定の質問に対処するために:

void foo(const char* const text); 

答えは適格な「いいえ」です:

  1. 2番目のconstは誰にも保証を提供しません。呼び出された関数は単にポインタtextをコピーしてコピーを修正することができます。

  2. APIを別の単語でクラッタし、値を追加しません。

が、2番目のconstは、発信者の利益のために存在しないことを反論はありますが、foo()の実装のために。

この場合、誤って変更することなく使用できるconstデータへの安全なconstポインタが提供されます。

これに対するカウンターカウンターの引数は、インターフェイスを介したリーク実装の詳細です。

+0

あなたのポイント1と2に関しては、トップレベルの 'const'がシグネチャに影響しないことを理解していないコード解析ツール(IDEだと思います)が少なくとも1つあり、if実装には宣言のない最上位の 'const'があります。このようなツールの問題は、宣言でもトップレベルの 'const'を使う良い実用的な理由になります。 –

+0

このようなツールの問題は、そのツールを使用しないでください* –

0

const次のコードでは、変数が変更されていないことを一目で確認できます。したがって、コードをより迅速に理解することができます。だから一般的なアドバイスはどこにでもコードを広げてconstのどこにでも置くことです。

C++ 11の移動セマンティクスがそのアドバイスと競合します。例えば、ある関数がstring引数をとり、その値をどこかに格納した場合、正式な引数はではなくでなければなりません。constとなるので、効率的にmovedを得ることができます。私の意見では、ここに欠けている言語機能があります。この時点以降、変数は使用できません。コンパイラが知っているので、論理的にconstそれが有用な価値を持つコードの範囲。

つまり、constconstexprのキーワードで提供される限定された種類のconstでもC++は完全にサポートしていません。それは残念です。しかし、(移動の最適化が妨げられるため)すべての状況で簡単にconstを使用することができない場合でも、良いプログラマは、可能な限り多くの制約があるため、他の懸念事項と矛盾しない場所であれ、コードの効果、そのコードの理解と維持に役立ちます。

関連する問題