为什么我可以将 std::map 的键传递给需要非常量的函数?
Why can I pass the key of std::map to a function that expects non-const?
根据std::map
documentation,它把键值对存储在std::pair<const Key, Value>
中,所以map中的键是const。
现在假设我有一个 std::map
,其中键是指向某些对象的指针。
struct S {};
struct Data {};
using MyMap = std::map<S*, Data>;
我们还假设有一个函数 foo
接受 S*
参数。
void foo(S* ptr) { /* modify the object (*ptr) */ }
现在,问题是:当我使用基于范围的 for 循环遍历 MyMap
时,我能够将地图元素键传递给 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?
}
所以,即使我的 static_assert
成功了(所以我假设 elem.first
的类型是 const S*
),对 foo
的调用编译得很好,因此看起来好像我能够修改 pointer-to-const 后面的对象。
为什么我能做到?
P.S. 这里有一个 live example at Coliru 可以说明我的观点。为简洁起见,我使用 int
而不是 S
和 Data
.
这里有一个更简单的例子,看看你能不能算出来:
void f(int); // takes a non-const int
int main() {
std::set<int> s; // elements are const ints
for (auto n : s) {
f(n); // OK!?
}
}
so I assume that the type of elem.first
is const S*
没有。 map
中存储的密钥是 const
,这意味着对于 std::map<S*, Data>
,密钥将是 S* const
(即 const
指针),而不是 const S*
(即指向 const
的指针)。所以传给foo(S* ptr)
就好了,const
指针本身会被复制到参数
正如您提到的,std::map<K, V>::value_type
是 std::pair<const K, V>
。那么当 S*
代替 K
时,const K
是什么?可能会让您感到惊讶的答案不是 const S*
。而是 S* const
.
根据std::map
documentation,它把键值对存储在std::pair<const Key, Value>
中,所以map中的键是const。
现在假设我有一个 std::map
,其中键是指向某些对象的指针。
struct S {};
struct Data {};
using MyMap = std::map<S*, Data>;
我们还假设有一个函数 foo
接受 S*
参数。
void foo(S* ptr) { /* modify the object (*ptr) */ }
现在,问题是:当我使用基于范围的 for 循环遍历 MyMap
时,我能够将地图元素键传递给 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?
}
所以,即使我的 static_assert
成功了(所以我假设 elem.first
的类型是 const S*
),对 foo
的调用编译得很好,因此看起来好像我能够修改 pointer-to-const 后面的对象。
为什么我能做到?
P.S. 这里有一个 live example at Coliru 可以说明我的观点。为简洁起见,我使用 int
而不是 S
和 Data
.
这里有一个更简单的例子,看看你能不能算出来:
void f(int); // takes a non-const int
int main() {
std::set<int> s; // elements are const ints
for (auto n : s) {
f(n); // OK!?
}
}
so I assume that the type of
elem.first
isconst S*
没有。 map
中存储的密钥是 const
,这意味着对于 std::map<S*, Data>
,密钥将是 S* const
(即 const
指针),而不是 const S*
(即指向 const
的指针)。所以传给foo(S* ptr)
就好了,const
指针本身会被复制到参数
std::map<K, V>::value_type
是 std::pair<const K, V>
。那么当 S*
代替 K
时,const K
是什么?可能会让您感到惊讶的答案不是 const S*
。而是 S* const
.