目录
string类在什么情况下触发写时才拷贝(Copy-On-Write)?
再谈swap

我们乍一看,为什么有三个swap函数呢?
算法库里面的swap,我们经常用,我们也知道,他们交换的时候需要构建临时变量,开空间,拷贝数据,再释放。代价是非常高的。于是这里我们引入了引用来解决这些问题。
对于两个 string 对象的交换 , 仅仅改变指向 不久可以了吗 ? string 的成员函数也的确是这么做的 。(复用了算法库的swap ! 仅仅是内部指针指向的交换)
void string::swap(string& s)
{
std::swap(_str, s._str);
std::swap(_size, s._size);
std::swap(_capacity, s._capacity);
}
但是实际上,当我们去调用swap,编译器并不会调用算法库内的swap,优先调用string 的全局函数swap,而且全局函数的swap 是对成员函数 swap 的封装。
构造的现代写法
拷贝构造
//传统写法
string::string(const string& s)
{
_str = new char[s._capacity + 1];
strcpy(_str, s._str);
_size = s._size;
_capacity = s._capacity;
其实下面要介绍的现代写法 , 没有效率的提升 , 只是简洁一点 ,本质是一种复用
//现代写法
string::string(const string& s)
{
string tmp(s._str);
swap(tmp);
}
现代写法借助了tmp来构造,s._str 是深拷贝的源头,调用成员函数 swap,交换 *this 与 tmp 的资源,交换后,*this 获得 tmp 的资源(就是拷贝后的字符串),而 tmp 持有原对象的空/无效状态。

赋值重载
//传统写法
string& string::operator=(const string& s)
{
if (this != &s)
{
delete[] _str;
_str = new char[s._capacity + 1];
strcpy(_str, s._str);
_size = s._size;
_capacity = s._capacity;
}
return *this;
}
string& string::operator=(const string& s) { if (this != &s) { string tmp(s._str); swap(tmp); } return *this; }//现代
这里还可以更加简洁一些
string& string::operator=(string& s)
{
swap(s);
return *this;
}
写时拷贝
1. 写时拷贝 : 就是一种拖延症 , 是再浅拷贝的基础之上增加了引用计数的方式来实现 。
2. 引用计数 : 用来记录资源使用者的个数 , 在构造时 , 将资源的计数给成1 , 每增加一个对象使用该资源 , 就给计数增加 1 , 当某个对象被销毁时 , 先给该计数减 1 , 然后再检查是否需要释放资源 , 如果计数为 1 , 说明该对象是资源的最后一个使用者 , 将该资源释放 , 否则就不能释放 , 因为还有其他对象在使用该资源 。
其实就是为了解决浅拷贝导致的问题 (析构多次,程序崩溃; 一个对象的修改影响另一个对象)
这个方式其实现在差不多都淘汰了 ,早期的g++使用 ,现在基本不用。
string类在什么情况下触发写时才拷贝(Copy-On-Write)?
哦,什么时候会发现写时才拷贝?很显然,当然是在共享同一块内存的类发生内容改变时,才会发生Copy-On-Write。比如string类的[]、=、+=、+、操作符赋值,还有一些string类中诸如insert、replace、append等成员函数,包括类的析构时。
修改数据才会触发Copy-On-Write,不修改当然就不会改啦。这就是托延战术的真谛,非到要做的时候才去做。
接下来我们再来了解一些特殊的编码
编码
unicode
统一码(Unicode),也叫万国码、单一码,由统一码联盟开发,是计算机科学领域里的一项业界标准,包括字符集、编码方案等。
统一码是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言,跨平台进行文本转换、处理的要求。
简单说,它是一个 超级大字典,收录了 14 万 + 字符,覆盖全球 150 + 语言,甚至包括 ** extinct languages(已灭绝的语言)。
unicode实际上覆盖一切:
语言:中文(简体 + 繁体)、英文、日文、韩文、阿拉伯文、希伯来文、希腊文、俄文……
符号:数学符号(∑√π)、货币符号(¥€$)、箭头(→↑)、标点(!?)。
表情:😂👍❤️🌍✨(emoji 本质是 Unicode 字符)。
特殊文字:盲文、古埃及圣书体、克林贡语(《星际迷航》里的外星语)……
甚至有 私人使用区(PUA),你可以自己造字!
版本更新:每年新增字符(比如 2023 年加入了 🩷🤌🦖),跟上时代。跨平台兼容:所有现代系统(Windows、macOS、Linux)、编程语言(Python、Java、JavaScript)都默认支持 Unicode。
utf-8
Unicode 给每个字符发了 “身份证”(码点),但直接存身份证号太浪费空间(比如英语字母本来 1 字节够,硬存成 4 字节纯纯浪费)。而utf-8 , 变长编码 , 而且还兼容 ASCII 码 。
核心优点:省空间 + 兼容 ASCII + 无乱码,所以现在几乎所有系统、网页、编程语言都默认用它(比如你现在看的这行字,大概率就是 UTF-8 编码的)。
其他编码
(1)GBK / GB18030(中文编码)
GB2312:早期简体中文(6763个汉字)。
GBK:扩展版(支持繁体、生僻字)。
GB18030:强制国家标准,兼容Unicode。(2)Big5(繁体中文)
主要用于港台地区。
(3)Shift-JIS(日文)
日本Windows系统传统编码。
编码常见问题
为什么文本乱码?
可能是文件保存时用了错误的编码(比如用 GBK 存,用 UTF-8 打开)。解决办法:统一用 UTF-8 编码保存和读取。
UTF-8 和 UTF-16 选哪个?
- 文本以英语为主:选 UTF-8(省空间)。
- 文本以中文 / 日文为主:选 UTF-16(省 1/3 空间,但兼容性略差)。
- 编程推荐用 UTF-8(几乎所有工具默认支持)。
BOM 是什么
UTF-16 文件开头可能有
FF FE或FE FF,用来标记 “大端序” 或 “小端序”(类似告诉电脑 “先读左边还是右边”)。UTF-8 一般不需要 BOM。
string的编码

我们在文档里面经常看到类似于这种,实际上在编程中,
string以及后面的u16string(对应char16)、u32string(对应char32)、wstring(对应wchar) 存在 , 主要是为了适应不同的字符编码需求以及处理不同特性的文本 。
1万+

被折叠的 条评论
为什么被折叠?



