C++ 避免使用临时std::string调用boost::无序_映射::find

C++ 避免使用临时std::string调用boost::无序_映射::find,c++,boost,stdstring,unordered-map,C++,Boost,Stdstring,Unordered Map,我有以下类型: boost::unordered_map< std::string , Domain::SomeObject > objectContainer; 这里我主要担心的是,仅仅为了与不可变的std::string进行比较而构建一个std::string,似乎有点过分,因为std::string临时文件需要有自己的缓冲区,复制其中的const char*内容,然后使用它来运行find()方法 有没有一个快捷方式可以用来避免在这里创建一个临时的std::string。重新

我有以下类型:

 boost::unordered_map< std::string , Domain::SomeObject > objectContainer;
这里我主要担心的是,仅仅为了与不可变的
std::string
进行比较而构建一个
std::string
,似乎有点过分,因为
std::string
临时文件需要有自己的缓冲区,复制其中的
const char*
内容,然后使用它来运行
find()
方法


有没有一个快捷方式可以用来避免在这里创建一个临时的
std::string
。重新声明函数,如下所示:

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

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

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

尝试使用以下方法:-

   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
  }
void findStuff(常量字符*键)
{

std::string abc=(std::string)key;//您可以继承boost::unordered_映射并添加一个具有“char*”版本的查找,该版本为您处理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;
//boost::无序映射objectContainer;
类ObjectContainer::public boost::无序映射
{
公众:
迭代器查找(const char*key){const std::string constKey(key);返回boost::unordered_map::查找(constKey);}
const_迭代器find(const char*key)const{const std::string constKey(key);返回boost::unordered_map::find(constKey);}
};
ObjectContainer ObjectContainer;

我还没有测试过上面的内容。我当前使用boost 1.40的VS2008设置在输入const char*查找时没有问题(我也没有使用auto)。它在const char*和操作符[]函数方面有问题,我对操作符[]做了类似的操作允许访问objectContainer[“key”]之类的函数。

主要问题是容器的声明

boost::unordered_map< std::string , Domain::SomeObject > objectContainer;
boost::无序映射objectContainer;
如果查看来源,我们将看到:

template<typename Key, typename Mapped, ...> 
    class unordered_map;
iterator find(const Key &);
模板
类无序图;
迭代器查找(常量键&);
所以,接口有很强的限制。find方法始终使用键类型作为参数,并且在不更改容器键类型的情况下无法更改它

如果您确定在初始化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);
    }
};
class objectContainer:public boost::无序映射
{
std::string\u缓冲区;
公众:
typedef boost::无序的_映射被继承;
objectContainer(){u buffer.reserve(1024);}
继承的typename::迭代器查找(常量字符*键)
{
_缓冲区=键;
返回继承的::find(_buffer);
}
};
现在,缓冲区在构造函数中只分配一次内存,而不是每次调用find时

另一种方法是,使用您自己的密钥类型,它可以使用std::string和const char*,但在这种情况下,您应该定义哈希(
boost::Hash
),谓词(
std::equal_to
)和密钥类型的实现

大概是这样的:

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(); }
};
类密钥
{
公众:
虚拟~Key();
虚拟常量char*key()=0;//用于哈希和谓词
};
//谓词
结构等于密钥:二进制函数{
布尔运算符()(常数键和x、常数键和y)常数
{ 
return false;//TODO:此处比较键
}
};
类CharKey:公钥
{
常量字符*_键;
公众:
虚拟常量char*key(){return\u key;}
};
类StringKey:公钥
{
std::字符串_键;
公众:
虚拟常量char*key(){return_key.c_str();}
};
现在,您有一种方法可以获取const char*并在哈希和谓词中使用它。当您插入字符串时,您更喜欢使用StringKey。当find-CharKey时

boost::unordered_map< Key , Domain::SomeObject, KeyHashFunctor, equal_to_Key > objectContainer;
void findStuff(const char* key) {
  auto it = objectContainer.find(CharKey(key));
}
boost::无序映射objectContainer;
void findStuff(常量字符*键){
autoit=objectContainer.find(CharKey(key));
}
但是,在这种情况下,添加虚拟函数和创建关键对象可能会降低性能,并且使用objectContainer变得不舒服


//我不确定“时态”这个词在这里是否正确。你是《星际迷航》中的人物吗?@KerrekSB:《星际迷航》与它有什么关系?“时态”是一个真实的词,尽管你是对的,因为它在这里使用不正确。谢谢你修复它,我时不时地与西班牙的《星际迷航》混在一起……“轨道上的光明竞赛”…哈哈(LRiO一定一直在祈祷这个机会…Kerrek,所以如果我从你写的东西中正确推断,你会说你对我的问题的回答是“不要费心去避免临时的,传递一个const std::string可能会通过神奇的方法提示编译器避免缓冲区分配”?@lurscher:没有魔法。你通过常量引用传递字符串,而不是通过值传递字符串,因此你不会复制任何东西,而是引用现有字符串。当然,你必须在其他地方有一个现有字符串。@lurscher-Kerrek避免临时字符串的方法是首先不使用
const char*
参数。如果你使用
std::string
在任何地方,您都不需要任何转换!也许我想要的是一个类型,它是std::string的某种变体,是一个不可变的类似字符串的类型,只有一个对const char*的引用(用户负责const char*的生存期)@卢谢尔:也许吧。我们该告诉谁你的想法……但是你需要在地图上键入那种类型,而不是在
std::string
上。地图拥有它的关键对象。如果你不喜欢,你可能需要一个不同的容器。最好的解决方案是什么?我在问是否有办法避免临时的。逐个键的比较完全失败无序_图的点,应具有O(1)访问权限
boost::unordered_map< Key , Domain::SomeObject, KeyHashFunctor, equal_to_Key > objectContainer;
void findStuff(const char* key) {
  auto it = objectContainer.find(CharKey(key));
}