我知道在关联容器中更改对象的键是一个可怕的想法,但我想知道标准到底禁止我这样做。考虑:
#include <map>
#include <memory>
struct X { int i; };
struct lt
{
bool operator()( const std::shared_ptr< X >& lhs,
const std::shared_ptr< X >& rhs ) const
{
return lhs->i < rhs->i;
}
};
int main()
{
std::map< std::shared_ptr< X >, int, lt > m;
auto x = std::make_shared< X >();
x->i = 1;
m.insert( std::make_pair( x, 2 ) );
x->i = 42; // change key wrt the container!
}
我认为上面的应该是非法的,但我现在正在阅读标准已有一段时间了,而且我找不到任何实际使非法的内容。它在哪里?或者它是否隐藏在未来的缺陷报告中?
答案 0 :(得分:10)
如果您根据指定的比较器更改后任意两个键的比较不同,则会在程序中注入未定义的行为。
根据C ++ 11标准的第23.2.4 / 3段([associative.reqmts]):
短语“等价键”是指比较所强加的等价关系,而不是 密钥上的
operator==
。也就是说,如果进行比较,则认为两个键k1
和k2
是等效的 对象comp
,comp(k1, k2) == false && comp(k2, k1) == false
。 对于任意两个键k1
和k2
同一个容器,调用comp(k1, k2)
应始终返回相同的值。