2

C++ メンバー変数を const にするのは、オブジェクトの構築後に変更すべきでない場合は好んで行いますが、STL で変更する必要がある場合もあります。たとえば、const メンバーを持つクラスのベクトルがあり、そのベクトル内の 2 つの要素を交換しようとすると、STL は生成されたデフォルトを使用しようとしoperator=()、const メンバー変数が原因で失敗します。

operator=()オブジェクト全体が作成されているという点でコンストラクターのような気がするのでoperator=()、constメンバー変数を保持しながら何らかの方法で許可したいと思います。

C++03でこれを行う方法はありますか? そうでない場合、C++11 ではどうですか? おそらくインプレース構築はこれのためでしょうか?

class Foo {
  const int _id;

  static int _generate_unique_id();

public:
  Foo()
    : _id(_generate_unique_id()) {
  }
};

vector<Foo> foo_vector;

// Fill foo_vector with several entries:
//   [...]

// Try to swap the first and second elements of the vector:
swap(*foo_vector.begin(), *(foo_vector.begin() + 1));
// The above fails to compile due to const member variable _id
// prohibits us from using the default assignment operator.
4

4 に答える 4

0

あなたが望むのは、Java の不変イディオムのようなものです。これは、ポインター (およびガベージ コレクション言語) では優れていますが、C++ のような値セマンティック言語ではそれほど優れていません。

次の 2 つの解決策があります。

1 - インターフェイスでオブジェクトを不変にする

メンバーは非公開 (または非公開にする必要があります) であるため、クラス自体 (およびその友人) 以外は変更できません。したがって、必要なのは、(あなたが制御する) クラス内で誰も操作しないようにすることと、保護された/パブリック インターフェイスで他の人にその権限を与える方法を提供しないことだけです。

TL;DR: オブジェクトを非 const にします。クラス内で変更しないでください。const ゲッターを追加します。セッターを削除します (存在する場合)。

2 - std::unique_ptr<const Data> を使用する

ここでは、Java のイディオムに従います。オブジェクトはconstですが、ポインターは再属性化できます。これはまさにあなたが望むものです。

const Data *これは、例外の安全性のため、実際にはメンバーの代替よりも優れています。

おまけ: デストラクタを手動で呼び出してオブジェクトを再構築しないでください

それを示唆する答えがあります。

seheが最初に述べたように、そうしないでください

あなたのポイントは、コードの品質を向上させることです。つまり、コードはいずれかの時点で例外に対して安全である必要があります。また、オブジェクトの有効期間を手動で操作すると、高品質のコードでは使用できなくなります。

この件に関する Herb Sutter の記事を読んでください: http://www.gotw.ca/gotw/023.htm

于 2015-09-08T10:04:46.363 に答える
0

割り当て不可能なオブジェクトを標準ライブラリ コンテナーに格納するための解決策は、オブジェクトへの (スマート) ポインターを格納することです。常に理想的ではありませんが、実行可能です。

于 2013-04-26T14:29:49.050 に答える
-1

conston members は、プログラマーがメンバーの有効期間中にその値を変更できないようにするだけではありません。また、それを変更しようとする試みが未定義の動作であることを指定することにより、コンパイラの最適化を有効にします ( const メンバーと代入演算子を参照してください。未定義の動作を回避する方法は? )。

あなたが望むことを行う1つの方法は、プログラマーとして含まれている値を変更する可能性を残しながら、nonmodifiableセマンティックを提供するコンテナーを作成することです。const

template<typename T> class nonmodifiable {
   T t;
public:
   nonmodifiable(T t): t{std::move(t)} {}
   operator const T &() const { return t; }
   nonmodifiable &operator=(const nonmodifiable &) = delete;
};

あなたは今書くことができます:

class Foo {
  nonmodifiable<int> _id;
  // etc.
};

_idまた、含まれる値も でもないためconst、destruct-placement new dance を使用して値を再割り当てします。

Foo &operator=(const Foo &foo) {
   if (this != &foo) {
      _id.~nonmodifiable<int>();
      new (&_id) nonmodifiable<int>(foo._id);
   }
   return this;
}
于 2013-04-26T14:46:36.997 に答える