C ++ 11:使用unordered_set :: push将const const int *转换为int *

时间:2013-05-13 19:01:07

标签: c++ c++11 unordered-set const-cast

我有使用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删除了。

1 个答案:

答案 0 :(得分:2)

set的键被声明为指向int的指针int*。但是这个:

void push( const B& b )
{
    set.insert( &b.x );
}

传递常量int的地址,int const*,因此编译错误。

从参数中删除const将解决编译器错误,因为密钥类型为int const*,但这两种解决方案都会:

  • 允许程序的其他部分,对const实例传递给Bpush(),以更改其中一个键的值在集合中并打破集合不变量:

    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.
    
  • 引入setb引用的对象生命周期的依赖关系:

    A a;
    a.push({14, 23}); // a now contains a dangling pointer.
    

最安全的解决方案是存储int作为密钥,请参阅http://ideone.com/KrykZw进行在线演示(感谢bitmask发表评论)。


可能的解决方案:

    <击>
  1. 动态复制b.x。或者,
  2. 使用int const*作为密钥。或者最好(避免显式动态分配),
  3. 使用int作为键,而不是int*(请参阅http://ideone.com/KrykZw