繁体   English   中英

对于std :: string使用operator []是否安全

[英]Is it safe to use operator [] for std::string

我正在与旧的C风格界面作斗争。 我有一个像这样的签名功能:

 /// if return_value == NULL only the length is returned
 void f( char * return_value, size_t * size_only_known_at_runtime); 

我的问题是,以下代码是否安全?

std::size required;
f( NULL, &required );
std::string s;
s.resize(required);
f( &s[0], &required );

有没有更好的方法将数据输入字符串?

是的,它是安全的,至少从C ++ 11中是明确的。 来自[string.require],强调我的:

basic_string对象中的char类对象应连续存储 即,对于任何的basic_string对象s时,身份&*(s.begin() + n) == &*s.begin() + n应的所有值保持n使得0 <= n < s.size()

这是DR 530的解决方案。 在C ++ 11之前,这在标准中并不明确,尽管无论如何它都是在实践中完成的。

在C ++ 14中,此要求已移至[basic.string]:

basic_string是一个连续的容器(23.2.1)。

where [container.requirements.general]:

连续容器是一个支持随机访问迭代器(24.2.7)的容器,其成员类型iteratorconst_iterator是连续迭代器(24.2.1)。

其中[iterator.requirements.general]:

迭代器进一步满足以下要求:对于整数值n和可解除引用的迭代器值a(a + n)*(a + n)等价于*(addressof(*a) + n) ,称为连续迭代器

问题是代码是否存在

std::size_t required_size;
f( nullptr, &required_size );
std::string s;
s.resize( required_size );
f( &s[0], &required_size );

是安全的。

这取决于假设哪个C ++标准,但由于在C ++ 03和C ++ 98中对于required_size = 0的情况它是未定义的行为,一般的答案是否定的 ,一般来说它不安全。


在C ++ 03中, std::string没有正式保证有一个连续的缓冲区,但实际上所有现存的实现都有连续的缓冲区。 无论如何,现在在C ++ 11之后,连续缓冲区保证正式合并到标准中,将不会出现任何具有非连续缓冲区的新C ++ 03实现。 因此,这不是问题。

问题在于,在C ++ 03中, std::basic_string::operator[]定义如下:

C ++03§21.3.4/ 1

返回:如果pos < size() ,则返回data()[pos] 否则,如果pos == size() ,则const版本返回charT() 否则,行为未定义。

因此,对于非const字符串s大小为0,在C ++ 03它是未定义行为™做索引s[0]

在C ++ 11中,相应的段落§21.4.3/ 2表示如果pos < size()则结果是“ *(begin() + pos) pos < size() ,否则引用值为charT()的类型为T的对象; 参考值不得修改。“


无论编译器实现哪种C ++标准,这里的代码都有效:

 std::size_t required_size; f( NULL, &required_size ); // Establish required buffer size. if( required_size > 0 ) { std::string s( required_size, '#' ); f( &s[0], &required_size ); s.resize( strlen( &s[0] ) ); } 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM