【问题标题】:Is it possible to make a shallow copy of very large STL strings?是否可以制作非常大的 STL 字符串的浅拷贝?
【发布时间】:2011-08-29 03:15:02
【问题描述】:

下午好,我们正在构建重复数据删除器的原型。我们使用 STL 字符串数组来存储要删除的记录。数组如下所示:

std::string* StringArray = new std::string[NumberDedupeRecords]

记录非常大,高达 160,000,000 字节。当我们尝试将记录的std::string 版本存储到std::string* StringArray 中以进行重复数据删除时,STL 对字符串进行深拷贝并分配至少160,000,000 字节的新缓冲区。我们很快耗尽了堆内存并得到了std::bad_alloc exception。是否有避免深拷贝和std::bad_alloc 的解决方法?也许我们应该使用一种新的数据结构来存储要删除的std::string 记录,或者我们应该保存auto_ptr 的记录。

我们在这里展示一个代码sn-p:

std::string clara5(curr.getPtr()); 
char* const maryptr = (curr.getPtr() + n - curr.low()); 
maryptr[54] = '\x0'; 
StringArray[StringArrayCount] = clara5; 
curr.mPtr = (char*)StringArray[StringArrayCount].c_str(); 

std::multiset<Range>::iterator miter5 = ranges_type.lower_bound(Range(n));
(*miter5).mPtr = curr.mPtr; StringArrayCount += 1;

谢谢。

【问题讨论】:

  • 您能否发布代码 sn-ps,说明您如何将记录存储到 StringArray?
  • “dedupe”和“depupe”是什么意思?
  • This 可能会有所帮助。
  • @user258808,感谢您的回复。这是一些代码: std::string clara5(curr.getPtr()); char* const maryptr = (curr.getPtr() + n - curr.low()); maryptr[54] = '\x0'; StringArray[StringArrayCount] = clara5; curr.mPtr = (char*)StringArray[StringArrayCount].c_​​str();感谢您的帮助。 std::multiset::iterator miter5 = range_type.lower_bound(Range(n)); (*miter5).mPtr = curr.mPtr; StringArrayCount += 1;
  • @Frank 评论不适用于代码;改为编辑您的问题。

标签: c++ windows linux stl


【解决方案1】:

如果您认为有必要执行各种所有权策略,您可以简单地获取原始 std::string 的指针或引用,包括智能指针。

【讨论】:

  • 我认为通过boost::shared_ptrs(或等效)访问这些字符串是最好的方法。
  • @DeadMG,谢谢你的回答。我刚刚接受了你的回答。问题是采用指向原始 std:: 字符串的指针是假设我们在处理过程中通过在清理记录时删除所有垃圾字符来修改记录,那么我们最终会得到同一记录的多个副本并且很难跟踪其中是正确的。 smart auto_ptr 会解决这个问题吗?感谢您的帮助。
  • @Etienne de Martel,我认为您对 boost::shared 指针的想法很好。不幸的是,我们有一些 UNIX 客户。所以我将我们的 Windows 程序移植到了 LINUX/UNIX。问题是 UNIX 许可证有 5 到 6 年的历史。所以,我的主管不愿意使用 Boost,因为这意味着我们将花费昂贵的成本购买 Solaris 和 IBM-AIX UNIX 许可证,它们的 C/C++ 是否等同于 boost::shared_ptr?感谢您的帮助。
  • @Frank:我看不出使用 Boost 和必须购买许可证之间的联系。升压是免费的。但是,如果您使用指向 std::string 的指针,然后修改字符串,您将不会得到多个副本,因为它们是 same std::string。如果您处理原始字符串,然后通过指针访问它,它将反映更改。
  • @DeadMG,谢谢您的回答。我将尝试使用您将指针指向 std::string 的想法。至于 Boost,我使用 Boost 正则表达式库开发了一个大型产品。我下载了最新的 Boost 发行版,它在 Windows 和 Red Hat Linux 中完美编译。但是,当我尝试在我们 6 年的 UNIX 编译器上编译它时,我在模板副本上遇到了多个编译错误。所以我修改了 Boost 正则表达式源代码以在 Solaris 和 IBM AIX 上运行。最后,我结束了 3 个版本的 Boost 正则表达式源代码。我的主管告诉我这是 Subversion 的噩梦。谢谢。
【解决方案2】:

如果可能,与其尝试使用智能指针,不如更改代码,以便一次在内存中只有几个 std::string 实例。这当然取决于您的访问模式,但您可以一次加载和处理一个字符串(记录),而不是一次为所有字符串分配一个数组。

编辑:鉴于 OP 正在尝试删除重复项,这可能效果不佳。

【讨论】:

  • 克里斯托弗弗雷德里克,谢谢您的回答。我认为你在这里有一个好主意。我会试试看。我刚刚接受了你的回答。关键问题是因为我们删除了多个重复项,所以我们想缓存一些字符串。但是,我们的堆内存有限,所以我们不能对大的 std::string 进行太多的深拷贝,谢谢您的帮助。
【解决方案3】:

我认为你的问题的真正答案是使用绳子 - 请参阅 http://www.sgi.com/tech/stl/Rope.html - std::string 并不是真正设计用于非常大的字符串。

【讨论】:

  • 尼尔·巴特沃斯,谢谢您的回答。我会看看绳子。
猜你喜欢
  • 2015-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-12
  • 1970-01-01
相关资源
最近更新 更多