结构的矢量与const成员?

时间:2011-12-11 22:17:29

标签: c++ const c++03

假设我有

#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 个答案:

答案 0 :(得分:8)

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

您的选择是:

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

答案 1 :(得分:8)

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

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

  

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

从表64(Assignable要求):

  

在表64中,T是用于实例化容器的类型,t的值为Tu的值为(const 1}})T

     

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

理论上,std::vector等价物可以选择在所有情况下进行破坏和复制构造,但这不是已经选择的合同。如果不需要重新分配,那么对vector::operator=vector::assign之类的内容使用包含类型的赋值运算符可能会更有效。

答案 2 :(得分:3)

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

通常,如果定义一个类,编译器将为您生成该类的赋值运算符。但是,有些情况下编译器无法执行此操作。其中一种情况是当类具有常量成员时(注意指向const的指针是可以的)。

因此,在您的情况下,问题是const string name。它会阻止编译器生成operator=(),这反过来会阻止vector编译,即使您实际上没有在其元素上使用赋值。

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

P.S。编译器无法生成operator=的另一种情况是,当您的类具有作为引用的成员时。

答案 3 :(得分:1)

向量元素必须是可复制的,Student结构不是const成员。只需使用string name代替const string name即可。 除非您有特定要求,否则类中的常量成员很少有用。如果要阻止对成员的更改,请将其设为私有并添加公共getter函数。