Rad*_*nyx 1 c++ memory string concatenation
我想知道字符串和内存如何一起工作。
据我所知,我知道当创建一个字符串时,它会将一些字符数组 + '\0' 放入内存中。我也知道它们是一成不变的。那么,对于连接之类的事情,内存中会发生什么,允许您访问相同的字符串?
我不认为您连接的字符串或字符直接放在原始字符串的地址之后,因为这可能会重叠一些所需的内存。
在 C# 和其他语言中,您可以说:
string s = "Hello" ... s = s + '!'
这会创建一个新字符串吗?一个指向一个新位置并显示“Hello!”,而使原始位置永远不会被引用的位置?
或者字符串使用的默认字符缓冲区是否允许连接中存在一些空间?
您所质疑的表达式的行为已由标准明确定义,并且是实现所必需遵循的。该标准的相关章节如下:
\n\nC++11\xc2\xa7 21.4.8.1-11
\n\ntemplate<class charT, class traits, class Allocator> \n basic_string<charT,traits,Allocator>\noperator+(const basic_string<charT,traits,Allocator>& lhs,\n const charT* rhs);\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n返回:
\nlhs + basic_string<charT,traits,Allocator>(rhs)
这导致:
\n\nC++11\xc2\xa7 21.4.8.1-3
\n\ntemplate<class charT, class traits, class Allocator>\n basic_string<charT,traits,Allocator>\noperator+(const basic_string<charT,traits,Allocator>& lhs,\n basic_string<charT,traits,Allocator>&& rhs);\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n返回:
\nstd::move(rhs.insert(0, lhs))
最后...
\n\nC++11\xc2\xa7 21.4.2-22
\n\nbasic_string<charT,traits,Allocator>&\n operator=(basic_string<charT,traits,Allocator>&& str) noexcept;\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n效果:如果 *this 和 str 不是同一个对象,则按表 71 所示修改 *this。 [注意:有效的实现是 swap(str)。\xe2\x80\x94 结束\n 注意]
\n
换句话说,为+运算符的 rhs 创建一个临时值,然后使用 修改该右值引用rhs.insert(0,lhs),最后将结果发送到赋值运算符的右值引用版本,该版本可以有效地执行移动操作。
有关详细信息,请参阅该标准的相关部分。
\n\nC++03x 注释
\n\n有人要求我为 C++03x 提供相同的演练。我对该标准的最后(官方)版本并不确定,但作为参考,以下内容基于 ISO/IEC 14882:2003(E)。请自行决定使用。
\n\n还为 C++03x 定义了类似的演练,如下所述,并适当注明了标准的相关部分。
\n\nC++03x \xc2\xa7 21.3.7.1-5
\n\ntemplate<class charT, class traits, class Allocator>\n basic_string<charT,traits,Allocator>\noperator+(const basic_string<charT,traits,Allocator>& lhs, const charT* rhs);\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n返回:
\nlhs + basic_string<charT,traits,Allocator>(rhs)
因此,与 C++11 一样,临时值是根据表达式的rhs构造的。从那里...
\n\nC++03x \xc2\xa7 21.3.7.1-1
\n\ntemplate<class charT, class traits, class Allocator>\n basic_string<charT,traits,Allocator>\noperator+(const basic_string<charT,traits,Allocator>& lhs, \n const basic_string<charT,traits,Allocator>& rhs);\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n返回: basic_string(lhs).append(rhs)
\n
这里我们与 C++11 不同。我们构造lhs的临时值,然后使用成员函数附加给定的rhs(第一步中的临时值)append()。为了简洁起见,我省略了临时lhs的常量引用构造函数。这将我们带到......
C++03x \xc2\xa7 21.3.5.2-1
\n\nbasic_string<charT,traits,Allocator>&\n append(const basic_string<charT,traits>& str);\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n返回:
\nappend(str, 0, npos)
这会将调用转发到相关成员函数,该函数接受来自要枚举的 rhs 的起始和停止索引。这将我们带到...
\n\nC++03x \xc2\xa7 21.3.5.2-2..5 \n basic_string&\n 追加(const basic_string& str, size_type pos, size_type n);
\n\n\n\n\n要求: pos <= str.size()
\n\n抛出: out_of_range 如果 pos > str.size()。
\n\n效果:确定要附加的字符串的有效长度 rlen,作为 n 和 str.size() - pos 中较小的一个。如果 size() >= npos - rlen,则该函数将抛出 length_error。否则,该函数将 *this 控制的字符串替换为长度为 size() + rlen 的字符串,其中第一个 size() 元素是 *this 控制的原始字符串的副本,其余元素是 *this 的初始元素的副本由 str 控制的字符串,从位置 pos 开始。
\n\n返回:*这个。
\n
本质上,这对位置参数进行一些健全性检查,然后用连接的内容执行替换。最后,现在完成了赋值操作,我们可以对整个失败的目标执行赋值操作,这将我们带到......
\n\nC++03x \xc2\xa7 21.3.1-16
\n\nbasic_string<charT,traits,Allocator>&\n operator=(const basic_string<charT,traits,Allocator>& str);\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n效果:如果 *this 和 str 不是同一个对象,则修改 *this 如表 43 所示
\n\n返回:*这个
\n
表43表示以下所需的效果。
\n\n\n\n\n\n\n
data()- 指向数组的已分配副本的第一个元素,其第一个元素由str.data()\n\n
size()-str.size()\n
capacity()- 至少与size()
我对此的评估是,实施可以做它想做的事情来实现这些效果(在表 43 中;仍然需要此处所示的实施路径)。
\n\n我太累了,无法继续学习 C++98。我希望这已经足够了。
\n