在定位C++ 03时使用std :: basic_string <t>作为连续缓冲区是否合理?

Bil*_*eal 32 c++ string winapi stl c++03

我知道在C++ 03中,从技术上讲,std::basic_string模板不需要具有连续的内存.但是,我很好奇有多少实现存在于实际利用这种自由的现代编译器.例如,如果想要用来basic_string接收某些C API的结果(如下面的例子),分配一个向量只是为了立即将它变成一个字符串似乎很愚蠢.

例:

DWORD valueLength = 0;
DWORD type;
LONG errorCheck = RegQueryValueExW(
        hWin32,
        value.c_str(),
        NULL,
        &type,
        NULL,
        &valueLength);

if (errorCheck != ERROR_SUCCESS)
    WindowsApiException::Throw(errorCheck);
else if (valueLength == 0)
    return std::wstring();

std::wstring buffer;
do
{
    buffer.resize(valueLength/sizeof(wchar_t));
    errorCheck = RegQueryValueExW(
            hWin32,
            value.c_str(),
            NULL,
            &type,
            &buffer[0],
            &valueLength);
} while (errorCheck == ERROR_MORE_DATA);

if (errorCheck != ERROR_SUCCESS)
    WindowsApiException::Throw(errorCheck);

return buffer;
Run Code Online (Sandbox Code Playgroud)

我知道像这样的代码可能会略微降低可移植性,因为它意味着它std::wstring是连续的 - 但我想知道这个代码是多么不可移植.换句话说,编译器如何实际利用具有非连续内存的自由?


编辑:我更新了这个问题,提到C++ 03.读者应注意,在定位C++ 11时,标准现在要求basic_string是连续的,因此在定位该标准时,上述问题不是问题.

Jer*_*fin 25

我认为假设std :: string连续分配其存储空间是相当安全的.

目前,所有已知的std::string分配空间实现是连续的.

此外,当前的C++ 0x草案(N3000)[编辑:警告,直接链接到大型PDF]要求空间连续分配(§21.4.1/ 5):

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

因此,当前或将来实施std::string使用非连续存储的可能性基本上为零.

  • @Steve Jessop:不是,`std :: basic_string`是一个编译器功能,而不是Windows功能.编译代码运行的Windows版本在这里并不重要. (5认同)
  • 有道理.但是,您可能会说,"此代码仅在Microsoft编译器上受支持".仍然不是与Windows版本严格相同,但重点是您只需要担心一组固定的实现.未来的MS编译器将支持大部分或全部C++ 0x. (3认同)

Mic*_*urr 14

前段时间有一个问题是能够写入存储器,std::string就好像它是一个字符数组,它取决于a的内容是否std::string是连续的:

我的回答表明,根据一些备受好评的消息来源(Herb Sutter和Matt Austern),当前的C++标准确实需要std::string在某些条件下存储其数据连续(一旦你称为str[0]假设str是a std::string),那么这个事实几乎迫使任何实施.

基本上,如果你结合所做的承诺string::data(),string::operator[]()你得出结论,&str[0]需要返回一个连续的缓冲区.因此,Austern建议委员会只是明确表示,显然这就是0x标准中会发生什么(或者他们现在称之为1x标准?).

因此严格来说,实现不必std::string使用连续存储来实现,但它必须非常需要.并且您的示例代码通过传入来实现&buffer[0].

链接: