C++ 标准库中 string 使用的优化技术

往容器中添加元素,若是要使用移动语义,一样的使用 std::move.

int main(){
    std::string s{"hello world"};
    std::cout << (int*)(s.c_str()) << "\n";

    std::vector<std::string> vec;
    vec.push_back(std::move(s));

    std::cout << (int*)(vec[0].c_str());
	return 0;
}

得到的地址却不一样,说明并没有移动。原因其实是标注库使用 SSO(Small String Optimization)优化技术。典型的string 和 vector的实现都是包含:1、一个指向堆内存的指针 2、一个表示当前使用容量的size 3、一个表示当前申请的内存可以容纳最大元素的capacity。

不过由于堆内存申请相对于开销大,所以使用了SSO技术之后,可以将小字符串放到栈中。


对于一个长字符串,再做试验。


在VS2013 和 mingw gcc 7.1.0 上测试都如此。

在Linux gcc 4.8.5 上没有这个优化,即使字符串很短只有一个字节,输出的地址仍然一样,说明 Linux gcc 总是使用的移动语义。

另外一个字符串过去常用的优化是 COW(Copy On Write)。写时复制的原因是大多数时候,使用到的字符串并不会对其修改(像 python 中的字符串干脆就不能修改),所以在复制字符串时,只对其进行浅拷贝,到需要更改字符串时,再进行深拷贝,对深拷贝过来的内容进行修改。写时复制依赖 引用计数技术。

不过写时复制,对于 operator[]() 或者 .at() 来访问单个元素,有潜在的改写字符串的可能性,所以对于这两个成员方法也需要先深拷贝,这无疑导致很多复杂性。所以现在的编译器很少使用这个优化。

猜你喜欢

转载自blog.csdn.net/zhouguoqionghai/article/details/78729271