我有使用c ++ 11标准使用此代码进行转换的问题:
#include<unordered_set>
struct B
{
int x, y;
};
class A
{
struct hash
{
std::size_t operator()( int* const a ) const
{
return std::hash<int>()( *a );
}
};
struct equal_to
{
std::size_t operator()( int* const a, int* const b ) const
{
return std::equal_to<int>()( *a, *b );
}
};
private:
std::unordered_set< int*, hash, equal_to > set;
public:
void push( const B& b )
{
set.insert( &b.x );
}
};
任何人都知道为什么会这样?我可以解决在“推”的参数中删除“const”修饰符的问题。但我不想要它,因为参数“b”没有被修改。
编辑:我的代码简化产生了一个未引用的地址。我已经将结构B删除了。
答案 0 :(得分:2)
set
的键被声明为指向int的指针,int*
。但是这个:
void push( const B& b )
{
set.insert( &b.x );
}
传递常量int
的地址,int const*
,因此编译错误。
从参数中删除const
将解决编译器错误,因为密钥类型为int const*
,但这两种解决方案都会:
允许程序的其他部分,对const
实例传递给B
非push()
,以更改其中一个键的值在集合中并打破集合不变量:
A a;
B b1{17, 22};
B b2{30, 22};
a.push(b1);
a.push(b2);
b1.x = 30; // set no longer contains unique keys.
引入set
对b
引用的对象生命周期的依赖关系:
A a;
a.push({14, 23}); // a now contains a dangling pointer.
最安全的解决方案是存储int
作为密钥,请参阅http://ideone.com/KrykZw进行在线演示(感谢bitmask发表评论)。
可能的解决方案:
b.x
。或者,int const*
作为密钥。或者最好(避免显式动态分配),int
作为键,而不是int*
(请参阅http://ideone.com/KrykZw)