8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

具有 const 成员的结构向量?

Vilius Bikneris 2月前

92 0

假设我有#include #包括使用命名空间 std;struct Student{ const string name;int grade;Student(const string &name) : name(name) { }}...

假设我有

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

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

帖子版权声明 1、本帖标题:具有 const 成员的结构向量?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Vilius Bikneris在本站《sorting》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 这似乎可以使用 VC 2010 进行编译和链接。您能提供有关您的环境的更多信息吗?这是一个可以重现编译失败的完整测试用例吗?

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

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

    这些组件中存储的对象类型必须满足类型的要求 CopyConstructible 类型 Assignable 的附加要求

    从表 64( Assignable 要求):

    在表 64 中, T 是用于实例化容器的类型, t 的值为 T u 的值为 (可能 const ) T .

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

    理论上, std::vector 等效函数可以在所有情况下选择执行析构和复制构造,但这并不是所选择的契约。如果不需要重新分配,那么使用包含类型的赋值运算符进行诸如 vector::operator= 和之 vector::assign 可能会更加高效。

  • @Philipp:实际上,vector 在重新分配时不会分配任何内容。它通常仅复制或移动构造新范围,然后删除旧范围。

  • 嗯...为什么 vector 会执行复制赋值?它不能执行复制构造 + 销毁,而不是使用运算符 = 吗?

  • @OliCharlesworth:但是,为什么 insert 需要赋值呢?我认为它需要一个复制构造函数(使用 allocator::allocate),因为它不是分配给有效对象,而是分配给新分配的、未格式化的内存块,对吗?

  • SRP 2月前 0 只看Ta
    引用 7

    @Mehrdad:因为在伪代码中,它会做类似的事情:for (int i = size(); i > pos; i--) { elements[i] = elements[i-1]; }。

  • 简单的答案是:你不能。如果你有 const 成员变量,那么编译器就不能提供默认的复制赋值运算符。但是, std::vector 提供的许多操作都需要进行赋值,因此需要(公共)复制赋值运算符。

    您的选择是:

    1. 使 name const .
    2. 编写自己的复制赋值运算符,并想办法处理“复制”成员 const
  • A vect或, 经常需要移动元素。每次向量需要增长时,当您调用 push_back() 它时,它会重新分配内存以保持自身连续,并将所有现有元素复制到新空间中。此外,如果您调用 insert() or remove() 元素必须移动。为了 vector 能够做到这一切,元素必须是可复制分配的,这意味着您存储在向量中的类型必须具有定义的赋值运算符。

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

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

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

    PS 编译器无法生成的另一种情况 operator= 是当你的类有引用成员时。

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

返回
作者最近主题: