C++ 使用std::basic_string<;是否合理;t>;作为目标C+时的连续缓冲区+;03?
我知道在C++03中,从技术上讲,C++ 使用std::basic_string<;是否合理;t>;作为目标C+时的连续缓冲区+;03?,c++,string,winapi,stl,c++03,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
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;
我知道这样的代码可能会稍微降低可移植性,因为它意味着std::wstring
是连续的——但我想知道这段代码有多不可移植。换句话说,编译器如何真正利用非连续内存所允许的自由
编辑:我更新了这个问题,提到了C++03。读者应该注意,当针对C++11时,该标准现在要求
basic_string
是连续的,因此在针对该标准时,上述问题不是问题。结果未定义,我不会这样做。在现代C++堆中,读入向量然后转换成字符串的代价微乎其微。VS您的代码在windows 9中死亡的风险
另外,这是否需要一个常量强制转换&buffer[0]?当然,在这里分配一个向量是愚蠢的。在这里使用std::wstring也不明智。最好使用字符数组来调用winapi。在返回值时构造一个WString。 < P>我认为假定STD::String连续地分配它的存储是相当安全的。 目前,
std::string
的所有已知实现都连续分配空间
此外,C++0x()(编辑:警告,直接链接到大PDF)的当前草稿要求空间被连续地分配(<21.4.1/5):
类字符对象 应存储基本字符串对象 连续地。也就是说,对任何人来说 基本字符串对象,标识 &*(s.begin()+n)==&s.begin()+n 应适用于n的所有值前一段时间,有一个问题是,是否能够将
std::string
作为一个字符数组写入存储器,这取决于std::string
的内容是否连续:
string::data()
和string::operator[]()
所做的承诺结合起来,您就会得出结论,&str[0]
需要返回一个连续的缓冲区。因此奥斯特恩建议委员会明确这一点,很显然,0x标准(或者他们现在称之为1x标准)中会出现这种情况
因此严格来说,实现不必使用连续存储来实现std::string
,但它必须根据需要来实现。您的示例代码就是通过传入&buffer[0]
实现的
链接:
&buffer[0]
,而不是buffer.data()
,因为[]
返回一个非常量
引用,并通知对象其内容可能会意外更改
执行
buffer.data()
会更干净,但您应该更关心结构之间共享的内存,而不是连续内存<代码>字符串实现可以而且确实期望在修改对象时被告知<代码>字符串::数据特别要求程序不修改返回的内部缓冲区
除了将长度设置为10或其他值之外,一些实现很可能会为所有未初始化的字符串创建一个缓冲区
使用
向量
甚至是带有新[]
/删除[]
的数组。如果确实无法复制缓冲区,请在更改之前合法地将字符串初始化为唯一的字符串。字符串实现与windows API无关,因此与用户使用的windows版本无关。是的,根据标准,这是未定义的行为。但对我所知道的每一个编译器来说都是可以的。我很好奇到底有多少编译器利用了标准赋予它们的自由度。实际上,新版本的windows附带了新版本的c运行时。关键是,未定义意味着它在未来可能会神秘地改变,为什么要冒险呢?实际上,我从来没有发现过一个字符串impl不能将字符串作为一个好的经典数组进行布局。但我还是不想这么做,这并不意味着它在未来会神秘地改变。未定义意味着编译器可以按照自己的意愿实现它。一旦代码被编译,它的行为就不能改变,除非它调用动态库。由于字符串不调用DLL,windows的未来版本将不会破坏它。(除非我使用动态C运行时——那么我认为这是可能的,但仍然不太可能)我不是在问这样做是否是个好主意——我是在问是否有编译器关心这个问题。另外,这不需要常量强制转换&buffer[0]?
我们玩得开心吗?:-)我所见过的所有编译器都按照我们都期望的方式进行编译。好啊但我仍然不会这么做,除非你确定MSVC成功地给了你RVO(即使你有两个不同的回报,一个是临时的,一个是变量名),那么你就不“允许”担心额外的副本;-)我不相信RVO会优化向量之间的拷贝