如何正确使用 'mutable' 使 set 迭代器不是 const?
How to use 'mutable' correctly so the set iterator won't be const?
我试图在我的代码中删除员工并将他的薪水改回 0,但我在函数中得到的只是他的 ID。我为集合使用了内置的迭代器,但发现它是常量。我如何使用可变的或其他方式将他的薪水更改为 0?
我有一名员工和一名经理 - 经理可以雇用或解雇该员工,这将改变他的薪水(显然)。
这是我的代码:
class Manager : public Citizen {
protected:
int salary;
std::set<Employee> employees;
void removeEmployee(const int id) {
mutable std::set<Employee>::iterator employee;
for (employee = this->employees.begin(); employee != this->employees.end(); employee++) {
if (employee->getId() == id) {
employee->setSalary(0);
this->employees.erase(employee);
return;
}
}
throw EmployeeNotHired();
}
我得到的错误-
C:\Users\User\CLionProjects\hw2Cpp\Manager.h:53:50: error: non-member 'employee' cannot be declared 'mutable'
mutable std::set<Employee>::iterator employee;
^~~~~~~~
C:\Users\User\CLionProjects\hw2Cpp\Manager.h:57:42: error: passing 'const mtm::Employee' as 'this' argument discards qualifiers [-fpermissive]
employee->setSalary(0);
我该怎么办?
**** 编辑****
我尝试将其更改为:
class Employee : public Citizen {
protected:
mutable int salary;
mutable int score;
std::set<Skill> skills;
但是我还是没法把工资改成0
error: passing 'const mtm::Employee' as 'this' argument discards qualifiers [-fpermissive]
employee->setSalary(0);
事情不是这样的。如果 member 被标记为可变 (mutable int salary;
) 而不是迭代器,则可以通过 const 引用更改值。
但是,为什么要在删除之前将工资设置为零?而且无论如何,如果影响集合的顺序,则不允许更改集合中的值,因此通常是个坏主意。
std::set
的设计确保集合中的元素“无法修改”,即它们只能通过 const 引用访问。这是有充分理由的:std::set
依靠其元素的顺序在整个生命周期内保持不变,以维护其内部搜索树数据结构。
处理此问题的方法是:
- 将
setSalary
声明为 const 成员函数。 (这不是一个好主意,因为设置薪水可能确实会以 const 函数所不期望的方式修改对象。)
- Extract 雇员 (C++17)
//employee->setSalary(0);
//this->employees.erase(employee);
auto node = employees.extract(employee);
node.value().setSalary(0);
- 选择不同的数据结构,例如从 id 到
Employee
或 std::vector<Employee>
的 std::unordered_map<int, Employee>
映射。
然而,除非 setSalary
函数具有修改 Employee
对象以外的效果,否则只需从集合中删除该对象即可;无论如何,该对象已在此过程中被删除...
我试图在我的代码中删除员工并将他的薪水改回 0,但我在函数中得到的只是他的 ID。我为集合使用了内置的迭代器,但发现它是常量。我如何使用可变的或其他方式将他的薪水更改为 0? 我有一名员工和一名经理 - 经理可以雇用或解雇该员工,这将改变他的薪水(显然)。 这是我的代码:
class Manager : public Citizen {
protected:
int salary;
std::set<Employee> employees;
void removeEmployee(const int id) {
mutable std::set<Employee>::iterator employee;
for (employee = this->employees.begin(); employee != this->employees.end(); employee++) {
if (employee->getId() == id) {
employee->setSalary(0);
this->employees.erase(employee);
return;
}
}
throw EmployeeNotHired();
}
我得到的错误-
C:\Users\User\CLionProjects\hw2Cpp\Manager.h:53:50: error: non-member 'employee' cannot be declared 'mutable'
mutable std::set<Employee>::iterator employee;
^~~~~~~~
C:\Users\User\CLionProjects\hw2Cpp\Manager.h:57:42: error: passing 'const mtm::Employee' as 'this' argument discards qualifiers [-fpermissive]
employee->setSalary(0);
我该怎么办?
**** 编辑**** 我尝试将其更改为:
class Employee : public Citizen {
protected:
mutable int salary;
mutable int score;
std::set<Skill> skills;
但是我还是没法把工资改成0
error: passing 'const mtm::Employee' as 'this' argument discards qualifiers [-fpermissive]
employee->setSalary(0);
事情不是这样的。如果 member 被标记为可变 (mutable int salary;
) 而不是迭代器,则可以通过 const 引用更改值。
但是,为什么要在删除之前将工资设置为零?而且无论如何,如果影响集合的顺序,则不允许更改集合中的值,因此通常是个坏主意。
std::set
的设计确保集合中的元素“无法修改”,即它们只能通过 const 引用访问。这是有充分理由的:std::set
依靠其元素的顺序在整个生命周期内保持不变,以维护其内部搜索树数据结构。
处理此问题的方法是:
- 将
setSalary
声明为 const 成员函数。 (这不是一个好主意,因为设置薪水可能确实会以 const 函数所不期望的方式修改对象。) - Extract 雇员 (C++17)
//employee->setSalary(0); //this->employees.erase(employee); auto node = employees.extract(employee); node.value().setSalary(0);
- 选择不同的数据结构,例如从 id 到
Employee
或std::vector<Employee>
的std::unordered_map<int, Employee>
映射。
然而,除非 setSalary
函数具有修改 Employee
对象以外的效果,否则只需从集合中删除该对象即可;无论如何,该对象已在此过程中被删除...