具有 const 成员的结构向量?

发布于 2024-12-21 04:09:51 字数 465 浏览 2 评论 0原文

假设我有

#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"));
}

有没有办法做到这一点,或者我必须分配堆上的所有学生,并存储指向每个学生的指针?

Let's say I have

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

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

How do I, then, keep a vector of students?

int main()
{
    vector<Student> v;

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

Is there even a way to do this, or must I allocate all the students on the heap, and store a pointer to each of them instead?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

铃予 2024-12-28 04:09:51

你不能。您的类型违反了标准容器的“可分配”要求。

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

这些组件中存储的对象类型必须满足CopyConstructible的要求
类型 (20.1.3),以及 Assignable 类型的附加要求。

从表 64(可分配 要求):

在表 64 中,T 是用于实例化容器的类型,tT 的值,u 是一个值(可能是 constT

表达式:t = u;返回类型:T;后置条件:t 相当于 u

理论上,一个 std::vector 等价物可以在所有情况下选择进行销毁和复制构造,但这不是已选择的合同。如果不需要重新分配,那么使用包含类型的赋值运算符来处理 vector::operator=vector::assign 可能会显着提高效率。

You can't. Your type violates the "Assignable" requirement for standard containers.

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

The type of objects stored in these components must meet the requirements of CopyConstructible
types (20.1.3), and the additional requirements of Assignable types.

From table 64 (Assignable requirements):

In Table 64, T is the type used to instantiate the container, t is a value of T, and u is a value of (possibly const) T.

expression: t = u; return type: T; post-condition: t is equivalent to u

In theory, a std::vector equivalent could choose to do destruction and copy construction in all cases, but that's not the contract that has been chosen. If reallocation isn't required, then using the contained type's assignment operator for things like vector::operator= and vector::assign might be significantly more efficient.

半夏半凉 2024-12-28 04:09:51

简单的答案是:你不能。如果您有 const 成员变量,则编译器无法提供默认的复制赋值运算符。然而,std::vector 提供的许多操作都需要进行赋值,因此需要一个(公共)复制赋值运算符。

您的选项是:

  1. name 设为非 const
  2. 编写您自己的复制赋值运算符,并想出一种方法来处理“复制”const 成员。

The simple answer is: you can't. If you have const member variables, then the compiler can't supply a default copy-assignment operator. However, many of the operations that std::vector provides need to make assignments, and therefore require a (public) copy-assignment operator.

Your options are:

  1. Make name non-const.
  2. Write your own copy-assignment operator, and think of a way to deal with "copying" a const member.
姐不稀罕 2024-12-28 04:09:51

向量通常需要移动元素。每次调用 push_back() 时,向量需要增长,它都会重新分配内存以保持自身连续,并将所有现有元素复制到新空间中。另外,如果您调用 insert()remove() 元素必须
被转移。为了使向量能够完成所有这些操作,元素必须是可复制赋值的,这意味着您存储在向量中的类型必须定义赋值运算符。

通常,如果您定义了一个类,编译器将为您生成该类的赋值运算符。但是,在某些情况下编译器无法做到这一点。其中一种情况是类具有常量成员(请注意,指向常量的指针是可以的)。

因此,就您而言,问题在于 const string name。它会阻止编译器生成 operator=(),进而阻止 vector 进行编译,即使您自己实际上并未对其元素使用赋值。

一种解决方案是使 name 成为非 const。另一种是以某种有意义的方式编写您自己的 Student::operator=()。正如您所指出的,第三种方法是使用指针向量而不是对象向量。但接下来你必须处理它们的分配和取消分配。

PS 编译器无法生成 operator= 的另一种情况是您的类具有作为引用的成员。

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.

漫漫岁月 2024-12-28 04:09:51

向量的元素必须是可复制分配的,而您的 Student 结构由于 const 成员而不能复制分配。只需使用字符串名称而不是const string name即可。
除非您有特定要求,否则类中的常量成员很少有用。如果您想防止更改成员,请将其设为私有并添加公共 getter 函数。

Elements of vectors must be copy-assignable, which your Student struct isn't because of the const member. Simply use string name instead of const string name.
Unless you have a specific requirement, constant members in classes are seldom useful. If you want to prevent changes to the member, make it private and add a public getter function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文