【问题标题】:How to avoid constructing a new string?如何避免构造新字符串?
【发布时间】:2016-11-27 15:44:27
【问题描述】:

我有一个模拟二维向量的一维字符向量(这是一个要求)。这个向量是 000111,它相当于一个 2D 的 vector[0] = 000 和 vector[1] = 111。所以它有两个字符串,长度相同(在这种情况下为 3)。我想将每个字符串设置为std::unordered_map 中的键,所以我这样做:

#include <iostream>
#include <unordered_map>
#include <string>
#include <vector>

int main ()
{
  std::unordered_map<std::string, int> mymap;
  std::vector<char> keys(2 * 3); // 2 keys, each one of length 3
  for(int i = 0; i < 2; ++i)
  {
    for(int j = 0; j < 3; ++j)
    {
      keys[j + i * 3] = (i) ? '1' : '0';
    }
  }
  // keys = 000111

  for(int i = 0; i < 2; ++i)
  {
    mymap[std::string(keys.begin() + i * 3, keys.begin() + (i + 1) * 3)] = i;
  }

  for (auto& x: mymap) {
    std::cout << x.first << ": " << x.second << std::endl;
  }

  /*
  Output:
  111: 1
  000: 0
  */

  return 0;
}

这让我很不开心,因为我必须构造一个新字符串,然后将其插入到地图中。如果我能一步到位就可以了。可以吗?

【问题讨论】:

  • “建筑很差?” 是的。 char(0) != '0'
  • 我很傻@BaummitAugen,你是对的,我更新了问题,请重新阅读! :)
  • @gsamaras 和以前一样的问题。 ;) 试试keys[j + i * 3] = (i) ? '1' : '0';
  • 你可以使用&lt;string_view&gt;吗? en.cppreference.com/w/cpp/header/string_view你也可以滚动你自己的string_view。
  • 这让我很不开心,因为我必须构造一个新的字符串 不要让这样的愚蠢事情影响你的幸福。如果您因为程序的性能比预期的差 10% 而感到沮丧,我可以理解您,但不是因为您无法避免对性能的影响未知且可能可以忽略不计的操作。

标签: c++ string vector data-structures hashtable


【解决方案1】:

我认为这是 c++17 string_view 的直接替代品。 string_view 不拥有任何字符串,因此 const-ness 可能是个问题(请参阅插入地图时的 const-cast)

唯一需要做的改变是

  1. const-cast,你必须解决这个问题。
  2. 多图的类型。
  3. 注意#endif 处的 using 语句

我刚刚将一个类、一个哈希结构(在 std::! 中)和一些重载添加到您的代码中。

#include <iostream>
#include <unordered_map>
#include <string>
#include <vector>
#ifdef HAS_STRING_VIEW
#include <string_view>
#else

class lps_noz_view{
public:
    lps_noz_view() = delete;
    lps_noz_view(const char* start, size_t size):start(start), stop(start + size){}
    lps_noz_view(const lps_noz_view& ) = default;
    lps_noz_view(lps_noz_view&& ) = default;
    const char* begin(){  return start;}
    const char* end(){  return stop;}
    const char* begin() const{  return start;}
    const char* end() const{  return stop;}
    std::string to_string() const{  return std::string(start, stop);}
private:
    const char* start;
    const char* stop;
};

bool operator < (const lps_noz_view& lhs, const lps_noz_view& rhs){
    return lhs.to_string() < rhs.to_string();  
    // or use strncmp to avoid creating strings =)
}

bool operator == (const lps_noz_view& lhs, const lps_noz_view& rhs){
    return lhs.to_string() == rhs.to_string();  
    // strncmp
}
std::ostream& operator << (std::ostream& os, const lps_noz_view& rhs){
    return os << rhs.to_string();
}

namespace std{
template<>
struct hash<lps_noz_view>
{
    using argument_type = lps_noz_view;
    using result_type = size_t;
    size_t operator()(const lps_noz_view& arg) const{
        return std::hash<std::string>()(std::string(arg.begin(), arg.end()));
    }
};
};

using string_view = lps_noz_view;
#endif
// 
int main ()
{
  std::unordered_map<string_view, int> mymap;
  std::vector<char> keys(2 * 3); // 2 keys, each one of length 3
  for(int i = 0; i < 2; ++i)
  {
    for(int j = 0; j < 3; ++j)
    {
      keys[j + i * 3] = (i) ? '1' : '0';
    }
  }
  // keys = 000111

  for(int i = 0; i < 2; ++i)
  {
    mymap[string_view(const_cast<const char*>(&(*keys.begin()) + i * 3), 
            (i + 1) * 3)] = i;
  }

  for (auto& x: mymap) {
    std::cout << x.first << ": " << x.second << std::endl;
  }

  /*
  Output:
  111: 1
  000: 0
  */

  return 0;
}

【讨论】:

  • "或者使用 strncmp 来避免创建字符串 =)",长颈鹿,你是男人..我的意思是动物!不错。
  • 我觉得这是一个恰当的评论 =)
猜你喜欢
  • 2016-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-06
  • 2021-05-16
相关资源
最近更新 更多