C++ 标准:设置<;std::pair<;尺寸,标准::字符串>>;::find(),不带字符串副本构造

C++ 标准:设置<;std::pair<;尺寸,标准::字符串>>;::find(),不带字符串副本构造,c++,stl,C++,Stl,我有一组std::pairs,第二对是字符串。我想检查集合中是否存在一对 std::set< std::pair<size_t, std::string> > set_; bool exists(size_t x, const std::string& s) { std::set< std::pair<size_t, std::string> >::iterator i = set_.find(std::make_pair(x, s));

我有一组std::pairs,第二对是字符串。我想检查集合中是否存在一对

std::set< std::pair<size_t, std::string> > set_; bool exists(size_t x, const std::string& s) { std::set< std::pair<size_t, std::string> >::iterator i = set_.find(std::make_pair(x, s)); // copy of s is constructed by make_pair! return i != set_.end(); } std::setset; bool存在(大小x,常数std::string&s) { std::set::迭代器i=set_u.find(std::make_-pair(x,s));//s的副本由make_-pair构造! return i!=set_.end(); }
我经常调用这个函数(是的,非常经常),所以我希望执行这个检查,而不需要临时复制字符串。有没有一种方法可以做到这一点,它和我这里的方法一样简单和简洁,但是它不会临时复制字符串?使用STL或Boost容器的任何解决方案都很好。

使用指向字符串的指针并重写谓词较少(请参阅std::set的构造函数)

分析是否确实表明字符串副本在这里是一个严重的问题

如果是这样,您是否能够更改exists函数,使其接受
对而不是两个参数,并安排将字符串直接构造到对中,而不是单独构造


如果您不能做到这一点,您可以始终使用
共享\u ptr
作为
对的第二个元素,并编造一个比较函数来比较来自地址的字符串而不是值字符串。

您始终可以自行查找

static pair<size_t, std::string> helper(0,"");
typedef std::set< std::pair<size_t, std::string> >::iterator iterator_type;
helper.first = x;
for (iterator_type i = set_.lower_bound(helper); i != set_.end(); ++i) {
    if (i->first != x)
        return false;
    if (i->second == s)
        return true;
}
return false;
staticpairhelper(0,”);
typedef std::set::迭代器迭代器\u type;
helper.first=x;
for(迭代器类型i=set_u.lower_bound(helper);i!=set_u.end();++i){
如果(i->first!=x)
返回false;
如果(i->second==s)
返回true;
}
返回false;

不幸的是,在C++标准库中,如果不改变<代码> KEYYORYTYPE <代码>,就不能这样做。还有其他容器库具有模板参数化的find函数,该函数允许不同的查找类型和比较器(例如Boost.Intrusive)。除此之外,您可以希望优化器删除副本构造。(基准!)

编写一个保持目标字符串引用的函子:

struct match_str : public std::unary_function<bool, std::string>
{
  match_str(const std::string& s) : s_(s) {};
  bool operator()(const std::pair<size_t, std::string>& rhs) const
  {
    return rhs.second == s_;
  }
};
struct match\u str:public std::一元函数
{
match_str(const std::string&s):s_(s){};
布尔运算符()(常数std::pair&rhs)常数
{
返回rhs.second==s;
}
};
用法:

std::set< std::pair<size_t, std::string> >::iterator i = std::find_if( set_.begin(), set_.end(), match_str(s) );
std::set::迭代器i=std::find_if(set_u.begin()、set_u.end()、match_str(s));

但与内置查找不同,它没有
log(n)
查找时间。@ltjax:我编辑了答案,因此它会跳转到
log(n)
查找时间中具有正确大小的部分。不过,该部分中的搜索仍然是线性的。如果每个大小只有几个字符串,这将不明显。@rubenvb:If
unique\u ptr
仍然可用。它依赖于右值引用,而右值引用实际上还不在标准中,也没有在所有现代编译器中实现。@David:是的,但在简单的用例中它确实更好。
;)
删除副本并通过
O(n)
one交换
O(logn)
算法?我认为这会使事情变得更慢,而不是更快。@ltjax:那么@James Brock要求提供不复制字符串的“任何解决方案”。这就是常识!在优化问题中不要使算法变得更糟;-)我认为这可能是最好的答案。我使用的是C++03(没有C++0x r值引用特性,因此不能使用unique_ptr),是的,我确实希望保留O(logn)时间。这将是混乱的,但C++是凌乱的。这有一个坏的副作用,迫使您手动管理存储在容器中的内存。在原始代码中,当集合超出范围时,容器将自动释放字符串中保存的内存,通过将其更改为保存指针,集合析构函数将不会释放字符串。这会给代码的其他部分增加复杂性和脆弱性。你做错了。编写直截了当、干净、有效的代码。然后,在完成之后,对应用程序进行概要分析,并优化结果显示的慢的内容;不是猜测。这里有很多建议,在我有证据证明这个函数导致性能问题之前,我不应该担心这个函数的性能。我只想告诉阅读本文的任何人,这是一个非常好的建议。只是在这种情况下不行。复制字符串并不像你想象的那么昂贵。首先编写干净的代码,然后在证明它是一个瓶颈时对其进行优化。