在内存中操作 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 推送到向量中