简体   繁体   English

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

[英]avoid temporary std::string to invoke boost::unordered_map::find

I have the following type: 我有以下类型:

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

which is just a map to some domain object, using std::strings as keys. 使用std::strings作为键,这只是到某些域对象的映射。 Now, std::string can be constructed and compared with const char* . 现在,可以构造std::string并与const char* (no need for an explicit std::string temporary, although maybe a implicit conversion is happening?) (尽管可能正在进行隐式转换,但不需要显式的std::string临时变量?)

The problem happens when I try to do something like 当我尝试做类似的事情时,就会发生问题

void findStuff(const char* key) {
  auto it = objectContainer.find(key); //<---build error
}

My main concern here is that it seems a little bit overkill to build a std::string just to make a comparison against an inmutable std::string , because the std::string temporary will want to have its own buffer, copy the const char* content in it, and then use that to run the find() method. 我在这里主要担心的是,构建一个std::string只是为了与不变的std::string进行比较似乎有点过大,因为std::string临时将要拥有自己的缓冲区,复制const char*内容,然后使用该内容运行find()方法。

Is there a shortcut I can use to avoid the creation of a std::string temporary in here? 我是否可以使用快捷方式来避免在此处创建std::string临时文件?

Of course. 当然。 Redeclare your function like this: 像这样重新声明您的功能:

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

Now use std::string in the calling code right from the start. 现在,从一开始就在调用代码中使用std::string

//<---build error // <---生成错误

What error? 什么错 It should compile as-is. 它应该按原样编译。 Unfortunately there's no simple way to do what you'd like. 不幸的是,没有简单的方法可以完成您想要的事情。 I've been bitten by the same issue. 我一直被同一个问题咬伤。 :( :(

There are multiple problems: parameter type of find() , types of std::equal_to , std::hash and std::less 有多个问题: find()参数类型, std::equal_to类型, std::hashstd::less

You could run through all the keys one by one, and compare them with old strcmp if you really did not want to create any extra std::string. 如果您真的不想创建任何额外的std :: string,则可以一一遍历所有键,并将它们与旧的strcmp进行比较。 But Kerrek solution is the best in my opinion 但是我认为Kerrek解决方案是最好的

You could inherit the boost::unordered_map and add a find with a version for "char *" that handles the temp std::string for you. 您可以继承boost :: unordered_map并添加一个带有“ char *”版本的查找,该查找可以为您处理临时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;

Also take the above with a grain of salt as I have not tested that. 由于我还没有测试过,因此也可以将其与一粒盐一起服用。 My current setup VS2008 with boost 1.40 does not have an issue with feeding a const char * to find (I am also not using auto). 我当前使用boost 1.40的设置VS2008在提供const char *时没有问题(我也不使用auto)。 It does have an issue with const char * and the operator[] function to which I have done something similar for the operator[] function allowing access like objectContainer["key"] 确实存在const char *和operator []函数的问题,我对operator []函数做了类似的操作,允许像objectContainer [“ key”]这样的访问

Main problem is declare of your container. 主要问题是您的容器的声明。

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

If look to source we will see : 如果查看源代码,我们将看到:

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

So, you have strong restrictions by interface. 因此,您对界面有严格的限制。 Method find always use Key type as parameter and you can't change it without changing container key type. 方法查找始终使用键类型作为参数,并且不能在不更改容器键类型的情况下对其进行更改。

If you sure that lose too many time on initialization of std::string you can use buffer (if no threads). 如果您确定在std :: string的初始化上浪费了太多时间,则可以使用buffer(如果没有线程)。 For example : 例如 :

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);
    }
};

Now, buffer allocates memory only once in constructor, not every time when call find. 现在,缓冲区在构造函数中仅分配一次内存,而不是在每次调用find时分配内存。

Other way, use your own key type which can work std::string and const char *, but at this case you should to define implementation of Hash( boost::hash<Key> ), predicate ( std::equal_to<Key> ) with your Key type. 否则,请使用可以使用std :: string和const char *的键类型,但是在这种情况下,您应该定义Hash( boost::hash<Key> ),谓词( std::equal_to<Key> )和您的密钥类型。

Something like this : 像这样的东西:

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(); }
};

Now, you have one way to get const char * and use it in hash and predicate. 现在,您有一种获取const char *并将其用于哈希和谓词的方法。 When you insert string you prefer to use StringKey. 当您插入字符串时,您更喜欢使用StringKey。 When find - CharKey. 找到时-CharKey。

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

But, at this case added virtual functions and creating Key objects might reduce perfomance and working with objectContainer became non-comfortable. 但是,在这种情况下,添加虚拟函数和创建Key对象可能会降低性能,并且使用objectContainer变得不舒服。

Try using this :- 尝试使用这个:

   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
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 结合升压unordered_map,bind和std :: find_if - combine boost unordered_map, bind, and std::find_if 使用std :: string键从boost :: unordered :: unordered_map恢复值时出错 - Error recovering values from boost::unordered::unordered_map using std::string keys boost :: unordered_map()的find()方法上的问题 - problems on the find() method of boost::unordered_map() boost interprocess unordered_map string - boost interprocess unordered_map string 如何使用 boost::unordered_map 的 boost std::vector 序列化/反序列化 - How to serialize/deserialize with boost std::vector of boost::unordered_map 对std :: unordered_map进行Boost :: serialization <double, std::vector<double> &gt; - Boost::serialization of an std::unordered_map<double, std::vector<double>> 加快std :: map和boost:unordered_map []操作 - speeding up std::map and boost:unordered_map [] operation 的std :: unordered_map <std::String, myClass*> - std :: unordered_map :: erase()调用myClass&#39;DTor? - std::unordered_map<std::String, myClass*> - does std::unordered_map::erase() call myClass' DTor? std::unordered_map 和 boost::unordered_map 有什么区别? - What is the difference between std::unordered_map and boost::unordered_map? boost :: unordered_map缺少std :: unordered_map之类的reserve() - boost::unordered_map missing reserve() like std::unordered_map
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM