相关疑难解决方法(0)

从char*初始化std :: string而不复制

我有一种情况,我需要处理大量(许多GB)的数据量:

  1. 通过附加许多较小的(C char*)字符串来构建一个大字符串
  2. 修剪弦乐
  3. 将字符串转换为C++ const std :: string进行处理(只读)
  4. 重复

每次迭代中的数据都是独立的.

我的问题是,我想最小化(如果可能消除)堆分配的内存使用量,因为它目前是我最大的性能问题.

有没有办法将C字符串(char*)转换为stl C++字符串(std :: string),而不需要std :: string来内部分配/复制数据?

或者,我可以使用stringstreams或类似的东西来重用大缓冲区吗?

编辑:感谢您的回答,为清楚起见,我认为修改后的问题将是:

如何有效地构建(通过多个附加)一个stl C++字符串.如果在循环中执行此操作,其中每个循环完全独立,我如何重新使用此分配的空间.

c++ string memory-management stl

43
推荐指数
4
解决办法
2万
查看次数

为什么通过检索指向其数据的指针修改字符串是不允许的?

在C++ 11中,a的字符std::string必须连续存储,如第21.4.1/5节所述:

basic_string对象中的char类对象应连续存储.也就是说,对于任何basic_string对象,标识&*(s.begin()+ n)==&*s.begin()+ n应该适用于n的所有值,使得0 <= n <s.size ().

但是,这里是§21.4.7.1如何列出两个函数来检索指向底层存储的指针(强调我的):

const charT*c_str()const noexcept;
const charT*data()const noexcept;
1返回:指针p,使得p + i ==&operator [](i)为[0,size()]中的每个i.
2复杂性:恒定时间.
3要求:程序不得更改存储在字符数组中的任何值.

我可以想到的第3点的一种可能性是指针可以通过对象的以下用途而变得无效(第21.4.1/6节):

  • 作为任何标准库函数的参数,将非const basic_string作为参数引用.
  • 调用非const成员函数,除了operator [],at,front,back,begin,rbegin,end和rend.

即便如此,迭代器也会失效,但我们仍然可以修改它们,无论它们是什么.我们仍然可以使用指针,直到它变为无效以便从缓冲区读取.

为什么我们不能直接写入这个缓冲区?是因为它会使类处于不一致状态,例如,end()不会使用新结束更新?如果是这样,为什么允许直接写入类似的缓冲区std::vector

用例包括能够将a的缓冲区传递std::string给C接口以检索字符串而不是传入一个字符串,vector<char>并使用迭代器初始化字符串:

std::string text;
text.resize(GetTextLength());
GetText(text.data());
Run Code Online (Sandbox Code Playgroud)

c++ string buffer language-lawyer c++11

23
推荐指数
1
解决办法
2930
查看次数

如何在没有副本的情况下从字符串流中获取字符?

在不使用boost的情况下,从字符串流中提取一组字符的正确c ++ 11方法是什么?

如果可能的话,我想在没有复制的情况下这样做,因为使用它的地方是关键数据循环.但是,似乎std :: string不允许直接访问数据.

例如,下面的代码执行字符串流中的子字符串副本:

inline std::string left(std::stringstream ss, uint32_t count) {
    char* buffer = new char[count];
    ss.get(buffer, count);
    std::string str(buffer);  // Second copy performed here
    delete buffer;
    return str;
}
Run Code Online (Sandbox Code Playgroud)
  1. 我应该根据c ++ 11使用char*buffer吗?
  2. 如何绕过制作第二份副本?

我的理解是矢量初始化每个角色,所以我想避免这种情况.

此外,这需要传递给一个接受const char*的函数,所以现在运行后我被迫做一个.c_str().这也是副本吗?

能够传回一个const char*会很好,但这似乎违背了"适当的"c ++ 11风格.

要了解我想要做什么,这里"有效"我想用它:

fprintf( stderr, "Data: [%s]...", left(ststream, 255) );
Run Code Online (Sandbox Code Playgroud)

但是c ++ 11强制:

fprintf( stderr, "Data: [%s]...", left(str_data, 255).c_str() );
Run Code Online (Sandbox Code Playgroud)

我在这里制作了多少份该字符串?

如何将它减少到只有一个副本的字符串流?

c++ stringstream c++11

6
推荐指数
1
解决办法
5875
查看次数