避免临时std :: string来调用boost :: unordered_map :: find

时间:2012-02-25 12:40:59

标签: c++ boost stdstring unordered-map

我有以下类型:

 boost::unordered_map< std::string , Domain::SomeObject > objectContainer;

这只是一个域对象的映射,使用std::strings作为键。现在,std::string可以构建并与const char*进行比较。 (不需要明确的std::string临时,虽然可能会发生隐式转换?)

当我尝试执行类似

之类的操作时会出现问题
void findStuff(const char* key) {
  auto it = objectContainer.find(key); //<---build error
}

我主要担心的是,构建std::string只是为了与不可变std::string进行比较似乎有点过分,因为std::string临时将要拥有它自己的缓冲区,复制其中的const char*内容,然后使用它来运行find()方法。

我可以使用哪种捷径来避免在这里创建std::string临时?

6 个答案:

答案 0 :(得分:2)

当然。像这样重新声明你的功能:

void findStuff(std::string const & key);

现在从一开始就在调用代码中使用std::string

答案 1 :(得分:0)

如果你真的不想创建任何额外的std :: string,你可以逐个遍历所有键,并将它们与旧的strcmp进行比较。但在我看来,Kerrek解决方案是最好的

答案 2 :(得分:0)

你可以继承boost :: unordered_map并添加一个带有“char *”版本的find,它可以为你处理temp std :: string。

//boost::unordered_map< std::string , Domain::SomeObject > objectContainer;
class ObjectContainer::public boost::unordered_map< std::string , Domain::SomeObject >
{
public:
    iterator find(const char *key){const std::string constKey(key); return boost::unordered_map< std::string , Domain::SomeObject >::find(constKey);}
    const_iterator find(const char *key)const {const std::string constKey(key); return boost::unordered_map< std::string , Domain::SomeObject >::find(constKey);}
};

ObjectContainer objectContainer;

还要考虑上面的一点点,因为我没有测试过。我当前的设置VS2008与增强1.40没有问题,提供一个const char *来查找(我也没有使用auto)。它确实存在const char *和operator []函数的问题,我为operator []函数做了类似的事情,允许像objectContainer [“key”]

这样的访问

答案 3 :(得分:0)

主要问题是声明您的容器。

boost::unordered_map< std::string , Domain::SomeObject > objectContainer;

如果看来源,我们会看到:

template<typename Key, typename Mapped, ...> 
    class unordered_map;
iterator find(const Key &);

因此,您对界面有很强的限制。方法find始终使用Key类型作为参数,如果不更改容器键类型,则无法更改它。

如果您确定在初始化std :: string时丢失了太多时间,则可以使用缓冲区(如果没有线程)。例如:

class objectContainer : public boost::unordered_map<std::string, SomeObject>
{
    std::string _buffer;
public:
    typedef boost::unordered_map<std::string, SomeObject> inherited;

    objectContainer() { _buffer.reserve(1024); }

    typename inherited::iterator find(const char * key)
    {
        _buffer = key;
        return inherited::find(_buffer);
    }
};

现在,缓冲区在构造函数中只分配一次内存,而不是每次调用find时都是。

其他方式,使用你自己的密钥类型,它可以工作std :: string和const char *,但在这种情况下你应该定义哈希(boost::hash<Key>),谓词(std::equal_to<Key>)的实现使用您的密钥类型。

这样的事情:

class Key 
{
public:
virtual ~Key();

virtual const char * key() = 0; // for hash and predicate
};

// predicate
struct equal_to_Key : binary_function <Key,Key,bool> {
    bool operator() (const Key & x, const Key & y) const
    { 
       return false; // TODO : compare Key here
    }
};

class CharKey : public Key
{
const char * _key;
public:
   virtual const char * key() { return _key; }
};

class StringKey : public Key
{
std::string _key;
public:
   virtual const char * key() { return _key.c_str(); }
};

现在,您有一种方法可以获取const char *并在hash和谓词中使用它。插入字符串时,您更喜欢使用StringKey。找到时 - CharKey。

boost::unordered_map< Key , Domain::SomeObject, KeyHashFunctor, equal_to_Key > objectContainer;
void findStuff(const char* key) {
  auto it = objectContainer.find(CharKey(key));
}

但是,在这种情况下,添加虚拟函数和创建Key对象可能会降低性能,并且使用objectContainer变得不舒服。

答案 4 :(得分:0)

  

//&lt; ---构建错误

什么错误?它应该按原样编译。 不幸的是,没有简单的方法可以做你想做的事。我被同样的问题困扰了。 :(

存在多个问题:find()的参数类型,std::equal_to的类型,std::hashstd::less

答案 5 :(得分:-2)

尝试使用: -

   void findStuff(const char* key) 
   {
     std::string abc = (std::string)key; //<---build error
     auto it = objectContainer.find(abc); // Now use "abc to find in Map
  }