4

具有以下代码:

#include <iostream>
#include <set>
#include <string>
#include <functional>

using namespace std;

class Employee {
  // ...
  int _id;
  string _name;
  string _title;
public:
  Employee(int id): _id(id) {}

  string const &name() const { return _name; }
  void setName(string const &newName) { _name = newName; }

  string const &title() const { return _title; }
  void setTitle(string const &newTitle) { _title = newTitle; }

  int id() const { return _id; }
};

struct compEmployeesByID: public binary_function<Employee, Employee, bool> {
  bool operator()(Employee const &lhs, Employee const &rhs) {
    return lhs.id() < rhs.id();
  }
};

int wmain() {
  Employee emplArr[] = {0, 1, 2, 3, 4};
  set<Employee, compEmployeesByID> employees(emplArr, emplArr + sizeof emplArr/sizeof emplArr[0]);
  // ...
  set<Employee, compEmployeesByID>::iterator iter = employees.find(2);
  if (iter != employees.end())
    iter->setTitle("Supervisor");

  return 0;
}

我无法编译此代码(MSVCPP 11.0):

1>  main.cpp
1>d:\docs\programming\test01\test01\main.cpp(40): error C2662: 'Employee::setTitle' : cannot convert 'this' pointer from 'const Employee' to 'Employee &'
1>          Conversion loses qualifiers

这有助于编译:

  if (iter != employees.end())
    const_cast<Employee &>(*iter).setTitle("Supervisor");

问题:我知道map并将multimap它们的值存储为pair(const K, V)其中 K 是键而 V 是值。我们不能改变 K 对象。但是set<T>并将multiset<T>他们的对象存储为T,而不是const T。那么为什么我需要这个 const 演员?

4

4 回答 4

12

在 C++11 集合(和多重集合)中,指定iteratorasconst_iterator是一个常量迭代器,即不能使用它来修改键。这是因为对它们的任何修改都有可能破坏集合的不变量。(见 23.2.4/6。)

const_cast打开了未定义行为的大门。

于 2012-01-16T22:31:56.247 回答
4

a 中的值set不应该被修改。例如,如果您修改了您的员工 ID,那么它将在集合中的错误位置,并且集合将被破坏。

您的 Employee 有三个字段,并且您的集合正在使用 _id 字段operator<

class Employee {
  // ...
  int _id;
  string _name;
  string _title;

};

因此,您可能应该使用 amap<int,Employee>而不是您的集合,然后您就可以修改名称和标题。我也会将_idEmployee 字段设为 a const int _id

(顺便说一句,以 开头的标识符_在技术上是保留的,应该避免使用。它从来没有给我带来任何麻烦,但现在我更喜欢将下划线放在变量名的末尾。)

于 2012-01-16T22:45:39.883 回答
2

在 C++ 中,您不能修改相关 STL 容器的键,因为您会破坏它们的顺序。当您希望更改密钥时,您应该 (1) 找到现有密钥,(2) 删除它,以及 (3) 插入新密钥。

不幸的是,虽然这并不太吸引人,但它就是关联容器在 STL 中的工作方式。

于 2012-01-16T22:34:06.837 回答
0

const你可以通过一个间接的方式逃脱。

但请注意不要更改给定排序容器中元素的顺序。

于 2012-07-21T02:04:54.957 回答