c – 处理映射键中指向值的常量

我有以下代码:

#include <map>
using namespace std;
struct A {};

map</*const*/ A *, int> data;

int get_attached_value(const A *p) {
    return data.at(p);
}
void reset_all() {
    for (const auto &p : data) *p.first = A();
}

我的问题是,当我在数据类型中注释和取消注释const时,此代码在类型错误上失败.有没有什么办法可以解决这个问题而不使用const_cast并且不会丢失get_attached_value中的const?

最佳答案 问题似乎是在pointee类型中,它在两个指针声明中都必须相同(map key type和get_attached_value的参数).

OP的代码使用const A *,它是指向类A的const实例的指针(另一种拼写是A const *).在map声明和get_attached_value’参数中保留这个const几乎可以正常工作,但reset_all不允许你为* p.first分配一个新值,因为结果类型是A const& (不能分配).

删除两个consts也是有效的,但是OP希望在get_attached_value中保留一个const.

OP的要求的一个解决方案,保持尽可能多的consts,似乎是将指针类型更改为指向非const实例A的const指针.这将使reset_all保持工作,同时允许在两个映射中使用const指针声明和get_attached_value的参数:

#include <map>
using namespace std;
struct A {};

map<A * const, int> data;

int get_attached_value(A * const p) {
    return data.at(p);
}
void reset_all() {
    for (const auto &p : data)
        *p.first = A();
}

另一个可能的解决方案,map的键为非const但get_attached_value的参数const,可以使用std :: lower_bound和自定义比较器来替换data.at()调用:

#include <map>
#include <algorithm>

using namespace std;
struct A {};

map<A*, int> data;

int get_attached_value(A const * const p) {
    auto it = std::lower_bound(data.begin(), data.end(), p,
        [] (const std::pair<A* const, int>& a, A const* const b) {
            return a.first < b;
        }
    );
    return it->second;
}
void reset_all() {
    for (const auto &p : data)
        *p.first = A();
}

但是,此解决方案的效率远低于使用map的本机搜索功能的解决方案 – std :: lower_bound uses linear search when input iterators are not random access.

总之,C 11或更低版本中最有效的解决方案可能使用const指针作为映射的键,并使用reset_all函数中的const_cast.

关于const表示法和指针的更多阅读可以在here找到.

点赞