4

C ++ FAQMatrixは、トリッキーなnew deleteコードを避けるためにテンプレートコンテナを定義しています。チュートリアルによると、添え字演算子はペアになることがよくありますか?なんでそうなの?

T&       operator() (unsigned i, unsigned j); 
T const& operator() (unsigned i, unsigned j) const;

なんでそうなの?

これは、const-overloadingとも呼ばれます。

FAQは手がかりを与えます。追加のコメントはありますか?

特に、mutate()constオブジェクトでのみ安全に使用される特定のルールを遵守する必要がありますか?

4

2 に答える 2

8

簡単に言うと、割り当てには左側と右側の2つの側面があるためです。

非constバージョン:T& operator() (unsigned i, unsigned j);主に割り当ての左側を対象としています(つまり、割り当てのターゲットとして使用されます)。

constバージョン:T const& operator() (unsigned i, unsigned j) const;割り当ての右側のみを対象としています。

ただし、そこでの表現の違いに注意してください。constバージョンは割り当ての右側でのみ使用できますが、non-constバージョンはどちらの側でも使用できます。ただし、const-qualifiedオブジェクトがある場合は、const-qualifiedメンバー関数しか呼び出せないため、この場合はまったく使用できません。これはまさにあなたが(少なくとも通常は)望んでいることです-それはあなたが変更すべきではないと言ったオブジェクトを変更することを防ぎます(それをconst-qualifiedすることによって)。

これまでのところ、これは通常、論理状態とビット単位のmutate状態の間に何らかの違いがあるオブジェクトにのみ使用されます。一般的な例は、いくつかの(通常は高価な)計算を怠惰に行うクラスです。値の再計算を回避するために、計算後に値を保存します。

class numbers { 
    std::vector<double> values;
    mutable double expensive_value;
    bool valid;
public:
    numbers() : valid(false) {}

    double expensive_computation() const { 
        if (valid) return expensive_value;
        // compute expensive_value here, and set `valid` to true
    }
};

したがって、ここでは、からの結果expensive_computationは純粋にの値に依存しますvalues。速度を気にしない場合は、ユーザーがを呼び出すたびに値を再計算するだけで済みますexpensive_computation。ただし、constオブジェクトで繰り返し呼び出すと、常に同じ結果が生成されます。したがって、一度呼び出すと、再度呼び出される可能性があると想定し、同じ高価な計算を繰り返し実行しないように、値をに保存しますexpensive_value。次に、ユーザーが再度要求した場合は、値を返すだけです。

つまり、論理的なconst観点からは、を変更してもオブジェクトは残りますexpensive_value。オブジェクトの表示状態は変更されません。私たちが行ったのは、constをより迅速に実行できるようにすることだけです。

これが正しくvalid機能するためには、ユーザーがの内容を変更するたびにfalseに戻す必要がありvaluesます。例えば:

void numbers::add_value(double new_val) {
   values.push_back(new_val);
   valid = false;
}

場合によっては、中程度の有効性が必要になることもあります。たとえば、ブール値を使用して現在かどうかを判断するのではなく、expensive_value追加された数値を正確に把握することで、より迅速に再計算できる場合があります。values有効かどうか。

おそらく、C++11がとの両方に関していくつかの新しい要件を追加することを追加する必要がconstありmutableます。長い話を短くするために、ほとんどの状況下で、スレッドセーフであるか、スレッドセーフであるかを確認する必要がありconstますmutableこれに関するハーブサッターのビデオを見たいと思うかもしれません。しかし、彼の結論mutableはおそらく少し誇張されていると思います(しかし、私の言葉を信じるよりも、あなたが自分で見て決定したほうがいいと思います)。

于 2013-03-15T15:23:02.237 に答える
2

オブジェクトに対する添え字演算子の呼び出しT&。最初の非定数演算子が呼び出されます。次に、検査および変更操作が許可されます。

オブジェクトに対する添え字演算子の呼び出しT const &、2番目のconst演算子が呼び出されます。次に、検査は許可されますが、変更は許可されません。

例はこちら

void f(MyFredList const& a)  ← the MyFredList is const
{
  // Okay to call methods that DON'T change the Fred at a[3]:
  Fred x = a[3];
  a[3].inspect();

  // Error (fortunately!) if you try to change the Fred at a[3]:
  Fred y;
  a[3] = y;       ← Fortunately(!) the compiler catches this error at compile-time
  a[3].mutate();  ← Fortunately(!) the compiler catches this error at compile-time
}

C ++ FAQのクレジット、詳細はこちら

于 2013-03-15T15:06:50.140 に答える