假设我的所有情况中,std::set
最简单:
std::set<std::string> my_set;
现在,我有一个函数可以接受const char*
,并且需要告诉我该字符串是否存在于集合中,该函数以最简单的方式实现:
bool exists(const char* str) {
return my_set.count(str) > 0;
}
现在,这是明显的效率损失。动态内存分配(潜在的)并随后进行释放是无缘无故的。
我们如何消除这种情况?我想将要成为键类型的std::string
与char*
进行比较。一种方法是在自定义比较器中使用unique_ptr<char>
而不是我的键类型,但是那样会很尴尬。
实际上,该问题可以推广到更广泛的情况,“如何在不转换为键类型的情况下调用提供的类型的比较?”
P.S。我见过std::string as map key and efficiency of map.find(),但是我对答案不满意,答案有效地重申了这种优化是不必要的,尽管它显然是错误的。
答案 0 :(得分:9)
您是正确的,默认情况下count
会将str
转换为std::string
可能会导致动态内存分配,并且至少会进行不必要的复制。幸运的是,C ++ 14以{p>的形式为count
添加了重载
template< class K >
size_type count( const K& x ) const;
这可以是任何类型。为了获得此重载,尽管您需要有一个比较器来定义名称为is_transparent
的成员类型(该类型无关紧要,只是它存在)。尽管我们可以使用C ++ 14中引入的新std::less<void>
,但不必写一个。通过提供模板化的operator()
,它可以用作透明的比较器。这意味着您只需要更改
std::set<std::string> my_set;
到
std::set<std::string, std::less<>> my_set;
// or
std::set<std::string, std::less<void>> my_set;
然后该集合将使用bool operator<(std::string, const char*)
进行比较,而无需进行临时或复制。