在内存中操作 std::strings 的 2D 动态数组的最有效方法是啥?

Posted

技术标签:

【中文标题】在内存中操作 std::strings 的 2D 动态数组的最有效方法是啥?【英文标题】:What is the most efficient way to manipulate a 2D dynamic array of std::strings in memory?在内存中操作 std::strings 的 2D 动态数组的最有效方法是什么? 【发布时间】:2011-08-03 01:10:10 【问题描述】:

我目前使用std::vector<std::vector<std::string> > MyStringArray 但是我在这里阅读了一些关于 SO 的 cmets,它们出于效率原因不鼓励使用嵌套向量。 不幸的是,在这种情况下,我还没有看到嵌套向量的替代示例。

【问题讨论】:

你为什么要构建一个 std::strings 的二维动态数组?告诉我们更多关于您数据的性质;这种结构在某些用途上很有效,但在其他用途​​上效率较低。 究竟什么是动态的?数组的维度在创建后会发生变化,还是保持不变? @bdonlan 最常见的情况是数据来自数据库。这些行是字符串的列(还有一些其他数据类型,但为了便于显示,还是将它们转换为字符串) @bdonlan。 'Manipulation' 主要是读取(索引到)单元格内容 v[x][y] 通常,您从数据库中逐行读取信息。您从查询中读取一行,对其进行处理,然后从查询中读取另一行。您通常不会一次加载每一行。并且有充分的理由。 【参考方案1】:

这是一个简单的动态二维数组,列号可在运行时配置:

class TwoDArray

  size_t NCols;
  std::vector<std::string> data;

public:
  explicit TwoDArray(size_t n) : NCols(n)  

  std::string & operator()(size_t i, size_t j)  return data[i * NCols + j]; 
  const std::string & operator()(size_t i, size_t j) const  return data[i * NCols + j]; 

  void set_number_of_rows(size_t r)  data.resize(NCols * r); 

  void add_row(const std::vector<std::string> & row)
  
    assert(row.size() == NCols);
    data.insert(data.end(), row.begin(), row.end());
  
;

用法:

TwoDArray arr(5); // five columns per row
arr.set_number_of_rows(20);
arr(0, 3) = "hello";
arr(17,2) = "world";

这只是一个完全随意和随机的例子。您的真实类显然必须包含适合您正在做的事情的接口方法;或者您可能决定根本不使用包装类并直接处理裸向量。

关键特性是通过(i,j) 的二维访问运算符,它替换了嵌套向量的[i][j]

【讨论】:

这看起来很有希望。让我做一些测试。我认为 NCold 是一个错字,你的意思是 Nicols。 add_row 函数也引用 v 而不是 row?【参考方案2】:

考虑到您的设计目标,这对我来说似乎是一个合理的设计。请注意,您应该避免调整外部向量大小的操作;这些可能会导致整个结构中所有数据的深层副本(这可能会通过 C++0x STL 实现有所缓解)。

【讨论】:

这也可以通过所谓的“交换”来缓解,其中向量中的可交换类型可以交换而不是复制。它基本上是在移动构造存在之前的移动构造。 VC++ 2008 的 STL 实现使用了这个技巧。【参考方案3】:

最有效的方法可能是让字符串在内存中连续(由空终止符分隔),并且每个字符串的引用数组连续,另一个连续 对每个数组的引用数组。

这是为了维护局部性并帮助有效地使用缓存,但这最终取决于您访问数据的方式。

【讨论】:

以上是关于在内存中操作 std::strings 的 2D 动态数组的最有效方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

字符串中最优化的连接方式

使用运算符 << 将 std::strings 推送到向量中

std::strings 有啥问题

在 C# 中替代 std::string [重复]

用字符串文字初始化时,std::strings 是不是以 '\0' 结尾?

std::string s1 "现代 C++", 3 与 std::string s1 str, 3