13

私が持っているとしましょう

#include <string>
#include <vector>
using namespace std;

struct Student
{
    const string name;
    int grade;
    Student(const string &name) : name(name) { }
};

では、どうすれば学生のベクトルを維持できますか?

int main()
{
    vector<Student> v;

    // error C2582: 'operator =' function is unavailable in 'Student'
    v.push_back(Student("john"));
}

これを行う方法はありますか、それともすべての学生をヒープに割り当て、代わりに各学生へのポインタを保存する必要がありますか?

4

4 に答える 4

9

簡単な答えは、できません。メンバー変数がある場合const、コンパイラはデフォルトのコピー代入演算子を提供できません。ただし、提供する操作の多くはstd::vector割り当てを行う必要があるため、(パブリック) コピー割り当て演算子が必要です。

オプションは次のとおりです。

  1. name対応にしconstます。
  2. const独自のコピー代入演算子を作成し、メンバーの「コピー」を処理する方法を考えてください。
于 2011-12-11T22:20:02.757 に答える
9

できません。あなたのタイプは、標準コンテナの「割り当て可能」要件に違反しています。

ISO/IEC 14882:2003 23.1 [lib.container.requirements] / 3:

これらのコンポーネントに格納されるオブジェクトの型は、型の要件CopyConstructible (20.1.3) とAssignable型の追加要件を満たす必要があります。

表64から(Assignable要件):

表 64 で、Tはコンテナーのインスタンス化に使用される型で、tは の値でありTuは (おそらくconst)の値ですT

式: t = u; 戻り値の型: T; 事後条件:tと同等u

理論的には、std::vector等価物はすべての場合に破壊とコピー構築を選択できますが、それは選択されたコントラクトではありません。再割り当てが必要ない場合は、含まれている型の代入演算子を および などに使用するvector::operator=vector::assign、はるかに効率的になる可能性があります。

于 2011-12-11T22:20:08.233 に答える
6

A vector often needs to move elements around. Every time a vector needs to grow when you call push_back() it reallocates memory to keep itself contiguous, and copies all the existing elements into the new space. Also if you call insert() or remove() elements must be shifted. For vector to be able to do all that the elements must be copy-assignable, which means that the type you store in the vector must have the assignment operator defined.

Generally, if you define a class, the compiler will generate the assignment operator for that class for you. However, there are cases when the compiler is unable to do that. One of these cases is when the class has constant members (note that pointers-to-const are ok).

So, in your case, the problem is the const string name. It prevents the compiler from generating operator=(), which in turn prevents vector from compiling, even though you do not actually use assignment on its elements yourself.

One solution is to make name non-const. The other is to write your own Student::operator=(), in some way that makes sense. The third way is, as you have pointed out, to use a vector of pointers rather than a vector of objects. But then you have to handle their allocation and de-allocation.

P.S. The other case when the compiler cannot generate operator= is when your class has members that are references.

于 2011-12-11T22:40:13.393 に答える
1

ベクトルの要素はコピー代入可能である必要がありますが、Student構造体はメンバーのためではありませんconststring nameの代わりに使用するだけですconst string name。特定の要件がない限り、クラスの定数メンバーが役立つことはほとんどありません。メンバーへの変更を防止したい場合は、非公開にし、公開ゲッター関数を追加します。

于 2011-12-11T22:21:08.263 に答える