2012-02-25 49 views
1

我有以下类型:避免临时的std :: string来调用的boost :: 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临时文件?

+1

类型我不知道“时间”在这里是正确的字你某种星际旅行的人 – 2012-02-25 12:45:53

+0

? @KerrekSB:“星际迷航”与它有什么关系?“Temporal”是一个真实的词,尽管你是对的,因为它不是正确的使用。 – 2012-02-25 13:07:26

+0

感谢您修复它,我不时混合与西班牙语 – lurscher 2012-02-25 13:16:53

回答

2

当然。再次声明你的函数是这样的:

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

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

+0

Kerrek,所以如果我从你写的东西正确推断,你会说那你对我的问题的回答是:“不要着急避免临时性,传递一个const std :: string可能暗示编译器通过神奇的方法来避免缓冲区分配”? – lurscher 2012-02-25 13:11:44

+0

@lurscher:没有魔法。您通过const引用传递字符串,而不是通过值传递,因此您不会复制任何内容,而是引用现有的字符串。当然,你必须在别处有一个现有的字符串。 – 2012-02-25 13:29:04

+2

@lurscher - Kerrek避免临时的方法是首先不要有'const char *'参数。如果你在任何地方使用'std :: string',你不需要任何转换! – 2012-02-25 13:34:38

0

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

+0

什么最好的解决方案?我在问是否有办法避免暂时的。一个一个的关键比较完全失败了一个unordered_map的点,它应该有O(1)的访问权限 – lurscher 2012-02-25 13:13:42

-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 
    } 
0

你可以继承的boost :: unordered_map并加上在“字符*”的一个版本,处理临时STD一个找到::你的字符串。

//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 *发现问题(我也没有使用汽车)。它对const char *和operator []函数有问题,我为operator []函数做了类似的操作,允许像objectContainer [“key”]那样访问。

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

现在,缓冲构造中分配内存只有一次,而不是每次调用时发现。

其他方式,使用自己的密钥类型可工作的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 *与哈希和谓语使用它。当你插入字符串时,你更喜欢使用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的工作变得不舒服。

0

// < ---建立自己的错误

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

有多种问题:参数类型的find()std::equal_tostd::hashstd::less

相关问题