c++ - 什么时候应该使用 const_iterator 而不是 auto

标签 c++ c++11

下面是一个例子,我认为它说明了使用 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/

相关文章:

c++ - 从静态函数调用非静态变量

c++ - std::condition_variable wait() 和 notify_one() 同步

c++ - 如何使用 WinAPI 重启 Windows 8/10 并进入高级启动选项?

c++ - 对 C++ 多态、可查找、二进制 I/O 接口(interface)的建议

c++ - 初始化通过引用传递的 vector

c++ - _Pass_fn : where is the constructor?

c++ - 关联容器中 std::array data() 失效的风险?

c++ - mprotect 和文件句柄

c++ - 是否有记录的方法来重置现有 std::exponential_distribution 对象上的 lambda 参数?

C++ 模式 : 1x base class + Nx derived classes BUT with a _last resort_ derived class