下面是一个例子,我认为它说明了使用 const_iterator 比使用“const auto”更可取的情况。这是因为容器不提供 cfind() 函数。还有其他选择吗?或者应该使用“const auto”而忽略 const 的缺失?
std::string GetJobTitle(const std::string& employee)
{
using EmployeeTitles = std::unordered_map<std::string, std::string>;
EmployeeTitles employees = { { "Alice", "Director" },{ "Bob","Manager" } ,{ "Charlie", "Developer" } };
// Option 1. const_iterator is access only:
EmployeeTitles::const_iterator itr = employees.(employee);
if (itr != employees.cend())
{
itr->second = "Project Manager"; // error C2678: The compiler prevents us changing the job tile which is what we want
return itr->second;
}
// Option 2. const auto is more concise but is not as safe:
const auto& itr2 = employees.find(employee);
if (itr2 != employees.cend())
{
itr2->second = "Project Manager"; // employee now has new title - how can we prevent this with the compiler but still use auto?
return itr2->second;
}
return "";
}
最佳答案
如果可能的话回避问题
使用 const
变量
您的示例并没有很好地说明问题。只要对常量更加“积极”,它就会消失。你不改变employees
根本没有,所以正确的解决方案是声明它 const
首先:
const EmployeeTitles employees = ...;
这更安全,因为它可以防止对 employees
的更改任何地方,而不仅仅是通过迭代器更改。
使用作用域来分隔常量/非常量代码
如果你做不到 employees
怎么办? const 因为你只能一 block 一 block 地填充它;例如,因为您从数据库中提取信息?将填充代码移动到构建器函数中。或者对于简单的情况,使用立即调用的 lambda:
const EmployeeTitles employees = [] {
EmployeeTitles employees;
for (const auto& record : database.employees()) {
// Probably some more processing would be done here in the real world.
employees.emplace(record.name(), record.job_title());
}
return employees;
}();
使用 const
成员函数
如果employees
是类的成员变量,您在成员函数中对其进行迭代,使该函数成为 const
.
作为一般规则
每当你遇到这个问题或类似的问题时,想办法使用const
变量/函数和/或范围界定以完全回避它。这将处理大多数情况。
如果您确实遇到了怎么办?
在那种情况下,我会选择您的选项 1:明确声明迭代器 const_iterator
结合 using
map 类型的声明。它简洁、可读、易于理解,是表达您的意图的最直接方式。
操纵 employees
常量的其他解决方案不是那么好,因为那不是你真正关心的。您实际上想要的是只读迭代器。摆弄 employees
的常量只是实现该目标的迂回方式。迂回代码更难理解。
另一方面,这并不意味着您会遇到清晰度方面的巨大问题。特别是std::as_const
也很简洁。
然而,对于 C++17 之前的代码库,您必须使用 const_cast
.这是一个良性的,因为它添加 const 并且它也不是太冗长。但我会根据看到 const_cast
的一般原则避免使用它。在一段代码中,乍一看总是有点吓人。正如@Swift 在评论中指出的那样,另一个好的可能性是实现您自己的 as_const
版本。 .
关于c++ - 什么时候应该使用 const_iterator 而不是 auto,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50165800/