为什么我可以将std :: map的键传递给期望非const的函数?

Vas*_*kin 3 c++ pointers stl const stdmap

根据std::map 文档,它存储键值对std::pair<const Key, Value>,因此映射中的键是const.

现在假设我有一个std::map键是指向某些对象的指针.

struct S {};
struct Data {};
using MyMap = std::map<S*, Data>;
Run Code Online (Sandbox Code Playgroud)

我们还假设有一个foo接受S*参数的函数.

void foo(S* ptr) { /* modify the object (*ptr) */ }
Run Code Online (Sandbox Code Playgroud)

现在,问题是:当我MyMap使用基于范围的for循环迭代时,我能够将map元素键传递给foo:

MyMap m = getMyMapSomehow();
for (auto elem : m)
{
    static_assert(std::is_const<decltype(elem.first)>::value, "Supposed to be `const S*`");
    foo(elem.first); // why does it compile?
}
Run Code Online (Sandbox Code Playgroud)

所以,即使我的static_assert成功(所以我假设它的类型elem.firstconst S*),foo编译的调用很好,因此看起来好像我能够修改指针到const后面的对象.

为什么我能做到这一点?

PS这是Coliru的一个实例,说明了我的观点.为简洁起见,我使用int而不是SData.

son*_*yao 5

所以我假设的类型elem.firstconst S*

否.存储的密钥mapconst,意思是std::map<S*, Data>,密钥将是S* const(即const指针),而不是const S*(即指针const).所以把它传递给它是好的foo(S* ptr),const指针本身将被复制到参数中.