【问题标题】:What is the recommended way to flatten a std::vector<CString> to a multi_sz using C++ / STL使用 C++/STL 将 std::vector<CString> 展平为 multi_sz 的推荐方法是什么
【发布时间】:2013-04-11 03:03:17
【问题描述】:

我想将存储在 std::vector 中的字符串列表 (ATL::CString) 写入 Windows 注册表中的 REG_MULTI_SZ 值。我知道如何在纯 C 中执行此操作(迭代一次以获得总长度,分配缓冲区,将字符串复制到以“\0”分隔的缓冲区)。

知道我使用 STL 尝试了以下操作(抱歉,我必须将 VS2010 与“for each”一起使用):

std::vector<TCHAR> multiline_sz;
for each ( CString entry in myStringList )
{
   TCHAR* buf = entry.GetBuffer();
   multiline_sz.insert(multiline_sz.end(), &buf[0], &buf[entry.GetLength()]);
   multiline_sz.push_back(L'\0');
}
multiline_sz.push_back(L'\0');

这可行,但我想知道是否有更优雅或更快的方式使用 STL。

【问题讨论】:

  • stackoverflow.com/questions/9277906/… 几乎重复。两个真正的区别是选择的分隔符(你想要一个 \0 而不是逗号),并在末尾添加额外的 nul。
  • 看起来很合理(假设循环头是伪代码)。 “更优雅”? - 可能不会,因为CString 没有迭代器接口。 “更快”? - 也许你可以事先总结大小(包括两者之间的0s)并做一个适当的multiline_sz.reserve(),尽管我不会保证显着的性能改进(我猜/希望你不会垃圾邮件无论如何,注册表都有整本书)。

标签: c++ string windows stl atl


【解决方案1】:

我建议使用 CString::GetString()(而不是 CString::GetBuffer()),因为它会返回一个指向以 NUL 结尾的字符串的指针,以便 只读 访问。

此外,还要注意CString::GetBuffer() 需要匹配的CString::ReleaseBuffer() 调用。

我还会简化你的代码,去掉不必要的&amp;buf[0]&amp;buf[&lt;index&gt;] 语法。

// Your pseudo code: 
// for each ( CString entry in myStringList )
{
  multiline_sz.insert(
      multiline_sz.end(), 
      entry.GetString(), // <-- current string's start
      entry.GetString() + entry.GetLength() + 1 // <-- include terminating NUL
  );
}

作为进一步的优化,您可以扫描整个输入字符串列表,并预先计算total所需的长度,并在@之前调用std::vector::reserve()在向量中预先分配空间987654329@ 电话。这将在插入过程中为您节省一些重新分配和副本。


P.S.如果您想使用 C++11 range-for 循环遍历 std::vector&lt;CString&gt;,可以使用以下语法:

for (const auto& entry : myStringList) 

【讨论】:

    【解决方案2】:

    CString::GetBuffer() 已经是零终止的,所以这样做是有效的

    for each ( CString entry in myStringList )
    {
       TCHAR const* buf = entry.GetBuffer();
       multiline_sz.insert(multiline_sz.end(), &buf[0], &buf[entry.GetLength()+1]);
    }
    

    【讨论】:

    • 谢谢。我保证一旦我被允许切换到 VS2012 就会使用“for(Cstring: entry in myStringList)”:)。
    • @majo 也不起作用。 for(auto &amp;&amp;entry : myStringList)for(auto iter=myStringList.begin(); iter!=myStringList.end(); ++iter) 如果您不允许切换。
    • @ChristianRau: for (const auto&amp; entry : myStringList) 对于实现 C++11 range-for 循环的编译器来说工作得很好。顺便说一句,我认为 2013 年的这个答案是错误的,因为它使用 CString::GetBuffer() 而不是 CString::GetString()。此外,&amp;buf[index] 语法在这种情况下是多余的,可以简化。几天前我发布了我认为更好的答案。
    猜你喜欢
    • 2014-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-10
    • 2013-05-08
    相关资源
    最近更新 更多