具有 const 成员的结构向量?
假设我有
#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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你不能。您的类型违反了标准容器的“可分配”要求。
ISO/IEC 14882:2003 23.1 [lib.container.requirements] / 3:
从表 64(
可分配
要求):理论上,一个
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:
From table 64 (
Assignable
requirements):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 likevector::operator=
andvector::assign
might be significantly more efficient.简单的答案是:你不能。如果您有 const 成员变量,则编译器无法提供默认的复制赋值运算符。然而,std::vector 提供的许多操作都需要进行赋值,因此需要一个(公共)复制赋值运算符。
您的选项是:
name
设为非const
。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 thatstd::vector
provides need to make assignments, and therefore require a (public) copy-assignment operator.Your options are:
name
non-const
.const
member.向量
通常需要移动元素。每次调用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 callpush_back()
it reallocates memory to keep itself contiguous, and copies all the existing elements into the new space. Also if you callinsert()
orremove()
elements mustbe 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 generatingoperator=()
, which in turn preventsvector
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 ownStudent::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.向量的元素必须是可复制分配的,而您的
Student
结构由于const
成员而不能复制分配。只需使用字符串名称
而不是const string name
即可。除非您有特定要求,否则类中的常量成员很少有用。如果您想防止更改成员,请将其设为私有并添加公共 getter 函数。
Elements of vectors must be copy-assignable, which your
Student
struct isn't because of theconst
member. Simply usestring name
instead ofconst 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.