5

次のメンバー関数があるとします。

void CFoo::regWrite( int addr, int data )
{
  reg_write( addr, data ); // driver call to e.g. write a firmware register
}

明らかに、この関数を呼び出しても、呼び出されたオブジェクトの内部状態は変更されません。ただし、このFooインスタンスが表すものはすべて状態を変更します。

このような状況ではFoo::regWrite(int addr, int data)、const関数である必要がありますか?

4

4 に答える 4

3

クラスの「論理的にconst」の意味を決定する必要がありCFooます。これは、クラスの目的によって異なります。

がいくつかのデータを参照しているCFooと解釈される場合、のインスタンスを介してそのデータを変更できることが理にかなっている場合があります。その場合、メンバー関数はになります。この例として、一部のデータを参照する他のタイプを検討してください。aまたはaの参照を変更できます。constCFooconstchar *constconst std::unique_ptr<char>

が一部のデータを所有しているCFooと解釈される場合は、のインスタンスを介した変更を禁止することが理にかなっている場合があります。この例として、要素が物理的にオブジェクトの一部ではない場合でも、要素が論理的に「オブジェクトの状態の一部」であるコンテナについて考えてみます。したがって、ではなくを返すconstオーバーロードがあり、メンバー関数はnon-constなどです。constCFoovector::operator[]const T&T&insert

于 2012-10-16T10:25:13.727 に答える
1

'const'がクラスに対して何を意味するかを定義するのはプログラマー次第です。指定子を使用すると、メンバーの値を変更するオブジェクトを作成するmutableこともできます。constハードウェアに関しては、構成を定数の正確さのターゲットと見なすことができます。構成が変更されない限り、オブジェクトは一定であると見なすことができます。

于 2012-10-16T10:13:17.363 に答える
1

クラス内の他のオブジェクトへのポインタがある場合にも、同様の問題が発生します。constメソッドは、他のオブジェクトの非constメソッドを呼び出して、それを変更できます。

ハードウェアをクラスによって参照される他のオブジェクトと見なす場合、ファームウェア設定を変更することは完全に有効です(「参照される」オブジェクトのみが変更されるため)。クラスでハードウェア(またはその一部)を「表す」場合は、メソッドをとしてマークしないことをお勧めしconstます。

ですから、それは主にあなたがクラスをどのように設計したかにかかっていると思います。

于 2012-10-16T10:25:29.590 に答える
1

これを見るには、最適化の角度とこの宣言のロジックの2つの方法があります。どちらがより重要かはあなたが決めることです。

最適化

編集:私はいくつかの間違った仮定をしました。コンパイラーは実際には以下の最適化を自由に行うことができないようであり、メソッドの本体を分析して変更が発生しないことを確認することによってのみ最適化を行います(それでも単純な場合のみ)。

これconstを使用すると、コンパイラーはもう少し最適化できます。オブジェクト内のフィールドは変更されないことがわかっているため、レジスタに格納されている場合はフィールドを保持し、オブジェクトフィールドregWriteが変更されていないことに依存する同様の最適化を実行できます。

このような定義を作成するときにコンパイラが依存するのはこれだけなので、これを使用してconstも問題はなく、理論的にはパフォーマンスを向上させることができます。

論理的に意味をなす

const破壊的な変化を目的とする方法があるのは直感的ではありません。プログラマーが持っている通常の直感は、私がconstメソッドのみを呼び出している限り、他のconstメソッドの結果は変わらないはずだということです。この書かれていない契約に違反した場合は、コンパイラがそれで問題ないとしても、人々が驚かれると期待してください。

ここでこれに違反するかどうかはわかりません。このクラスの他のコードに依存します。ただし、他の考慮事項(パフォーマンスなど)が重要でない場合は、const(私にとって)ほとんどの場合、「状態」の広義の定義として、「これを呼び出してもこのオブジェクトの状態は変更されません」というインターフェイス上のマーカーです。

ただし、これは曖昧な状況であり、状態変化をどのように考えるかはあなた次第です。ファームウェアオブジェクトを内部へのリンクを表すものと考える場合、レジスタを書き込んでもこのリンクについては何も変更されず、constです。基礎となるレジスタの状態を表すものと考える場合、レジスタへの書き込みは状態の変化です。

于 2012-10-16T10:15:08.843 に答える