简体   繁体   English

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

[英]Handling constness of pointed values in map keys

I have the following code: 我有以下代码:

#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();
}

My problem is that this code fails on a type error both when I comment and uncomment the const in the type of data . 我的问题是,当我在data类型中注释和取消注释const时,此代码在类型错误上失败。 Is there any way I can solve this without using const_cast and without losing the const in get_attached_value ? 有没有什么办法可以解决这个问题而不使用const_cast并且不会丢失get_attached_valueconst

The problem seems to be in the pointee type , which has to be the same in both pointer declarations (map key type and the get_attached_value 's argument). 问题似乎是在pointee类型中 ,它在两个指针声明中都必须相同(map key type和get_attached_value的参数)。

OP's code uses const A* , which is a pointer to a const instance of class A (an alternative spelling is A const * ). OP的代码使用const A* ,它是指向类Aconst实例的指针(另一种拼写是A const * )。 Leaving this const in both map declaration and in get_attached_value ' argument almost works, but reset_all does not allow you to assign a new value to *p.first , because the resulting type is A const& (which cannot be assigned into). 将此const保留在map声明和get_attached_value '参数中几乎可以正常工作,但reset_all不允许您为*p.first分配新值,因为结果类型是A const& (无法分配)。

Removing both consts works as well, but OP wants to keep a const in get_attached_value . 删除两个consts也是有效的,但是OP希望在get_attached_value保留一个const。

One solution for OP's requirements, keeping as many consts as possible, seems to be to change the pointer type to a const pointer to a non-const instance of A . OP的要求的一个解决方案,保持尽可能多的consts,似乎是将指针类型更改为指向A的非const实例的const指针 This will keep reset_all working, while allowing to use a const pointer in both map declaration and get_attached_value 's argument: 这将使reset_all保持工作,同时允许在map声明和get_attached_value的参数中使用const指针:

#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();
}

Another possible solution, with map's key as non-const but the get_attached_value 's parameter const, could use std::lower_bound with a custom comparator to replace the data.at() call: 另一个可能的解决方案,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();
}

However, this solution will be significantly less efficient than one that would use map 's native search functions - std::lower_bound uses linear search when input iterators are not random access . 但是,此解决方案的效率远低于使用map的本机搜索功能的解决方案 - 当输入迭代器不是随机访问时, std::lower_bound 使用线性搜索

To conclude, the most efficient solution in C++11 or lower would probably use a const pointer as the map's key, and a const_cast in the reset_all function. 总而言之,C ++ 11或更低版本中最有效的解决方案可能使用const指针作为映射的键,并使用reset_all函数中的const_cast

A bit more reading about const notation and pointers can be found here . 关于const表示法和指针的更多阅读可以在这里找到。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM