chr*_*ris 23 c++ string buffer language-lawyer c++11
在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节):
即便如此,迭代器也会失效,但我们仍然可以修改它们,无论它们是什么.我们仍然可以使用指针,直到它变为无效以便从缓冲区读取.
为什么我们不能直接写入这个缓冲区?是因为它会使类处于不一致状态,例如,end()不会使用新结束更新?如果是这样,为什么允许直接写入类似的缓冲区std::vector?
用例包括能够将a的缓冲区传递std::string给C接口以检索字符串而不是传入一个字符串,vector<char>并使用迭代器初始化字符串:
std::string text;
text.resize(GetTextLength());
GetText(text.data());
Run Code Online (Sandbox Code Playgroud)
Nic*_*las 34
为什么我们不能直接写入这个缓冲区?
我会说明一点:因为它是const.丢弃一个const值,然后修改该数据是......粗鲁.
现在,为什么呢const?这可以追溯到写时复制被认为是个好主意的日子,因此std::basic_string不得不允许实现支持它.获取指向字符串的不可变指针(例如,传递给C-API)而不会产生副本的开销将非常有用.所以c_str需要返回一个const指针.
至于为什么它仍然存在 const?嗯......这是标准中的一个古怪的东西:空终结符.
这是合法的代码:
std::string stupid;
const char *pointless = stupid.c_str();
Run Code Online (Sandbox Code Playgroud)
pointless必须是以NUL结尾的字符串.具体来说,它必须是指向NUL字符的指针.那么NUL角色来自哪里?实现有两种方法可以std::string实现:
std::string实现都有一个内部缓冲区,可用于单个NUL字符.std::string实现都将返回相同的指针.不应该强迫每个人都实施SSO.所以标准委员会需要一种方法来保持#2在桌面上.其中一部分是给你一个const字符串c_str().而且因为这个内存可能是真实的 const,而不是假的"请不要修改这个内存const",给你一个可变的指针指向它是一个坏主意.
当然,您仍然可以通过这样做获得这样的指针&str[0],但标准非常清楚,修改NUL终结符是一个坏主意.
现在,话虽如此,修改指针及其中的字符数组是完全有效的&str[0].只要你留在半开放范围[0,str.size()).你不能通过data或返回的指针来做到这一点c_str.是的,即使标准实际上要求 str.c_str() == &str[0]是真的.
这对你来说是一个标准.
| 归档时间: |
|
| 查看次数: |
2930 次 |
| 最近记录: |