__sso_string与std::string的区别

在学习muduo库源码的时候在,base文件夹下的type.h有

#ifdef MUDUO_STD_STRING
using std::string;
#else  // !MUDUO_STD_STRING
typedef __gnu_cxx::__sso_string string;
#endif

就想了解一下__sso_string和std::string 的区别:
主要参考了这篇博客:http://blog.csdn.net/kemawcz/article/details/52709747
我自己也进行了例子测试:编译器版本是GCC4.8.5 操作系统是centos7 IDE: eclipse Mars
因为这两种不同的字符串模式,涉及到了深拷贝和浅拷贝的问题。
首先测试了
__sso_string 短字符串情况

#include <iostream>
#include <ext/vstring.h>
using namespace std;
typedef __gnu_cxx::__sso_string  SSO_string;
int main() {
    SSO_string  str1 = "123456";
    SSO_string str2(str1);
    cout<<"str1对象地址="<<(long int )&str1<<"       str1C字符串地址"<<(long int )str1.c_str()<<endl;
    cout<<"str2对象地址="<<(long int )&str2<<"       str2C字符串地址"<<(long int )str2.c_str()<<endl;
    return 0;
}

运行结果:
str1对象地址=140734076030416 str1C字符串地址140734076030432
str2对象地址=140734076030448 str2C字符串地址140734076030464
发现短字符串的情况下,进行了深拷贝操作,而且内存分配位置很接近应该都是在栈上分配的内存。
然后测试一下比较长的字符串。

int main() {
    //SSO_string  str1 = "123456";
    SSO_string str1 = "11231dwadwfewfewfewfw=============dwfffffffffwaf3244444444444444455555543tttttttttttttttttttttdddddddddddddddddddddddddddddddddddddddddddddddddddddd";
    SSO_string str2(str1);
    cout<<"str1对象地址="<<(long int )&str1<<"       str1C字符串地址"<<(long int )str1.c_str()<<endl;
    cout<<"str2对象地址="<<(long int )&str2<<"       str2C字符串地址"<<(long int )str2.c_str()<<endl;
    return 0;
}

这个运行结果是:
str1对象地址=140729417014880 str1C字符串地址34193424
str2对象地址=140729417014912 str2C字符串地址34193584
同样进行了深拷贝操作,因为C字符串的地址不同,但是发现C字符串的地址和对象地址差距很大,应该是在堆上申请的内存。
那么接下来测试一下std::string

int main() {
    std::string  str1 = "123456";
    //std::string  str1 = "11231dwadwfewfewfewfw=============dwfffffffffwaf3244444444444444455555543tttttttttttttttttttttdddddddddddddddddddddddddddddddddddddddddddddddddddddd";
    std::string  str2(str1);
    cout<<"str1对象地址="<<(long int )&str1<<"       str1C字符串地址"<<(long int )str1.c_str()<<endl;
    cout<<"str2对象地址="<<(long int )&str2<<"       str2C字符串地址"<<(long int )str2.c_str()<<endl;
    return 0;
}

运行结果:
str1对象地址=140736195194224 str1C字符串地址29622312
str2对象地址=140736195194208 str2C字符串地址29622312
发现C字符串地址一样
我们再测试一下长度比较长的字符串:

int main() {
    //std::string  str1 = "123456";
    std::string  str1 = "11231dwadwfewfewfewfw=============dwfffffffffwaf3244444444444444455555543tttttttttttttttttttttdddddddddddddddddddddddddddddddddddddddddddddddddddddd";
    std::string  str2(str1);
    cout<<"str1对象地址="<<(long int )&str1<<"       str1C字符串地址"<<(long int )str1.c_str()<<endl;
    cout<<"str2对象地址="<<(long int )&str2<<"       str2C字符串地址"<<(long int )str2.c_str()<<endl;
    return 0;
}

运行结果:
str1对象地址=140731855771696 str1C字符串地址33902632
str2对象地址=140731855771680 str2C字符串地址33902632
依然是相同的,而且无论字符串长短,都应该是在堆上分配的内存。

那么根据上述博客中提到的COW实现方式:

int main() {
    //std::string  str1 = "123456";
    std::string  str1 = "11231dwadwfewfewfewfw=============dwfffffffffwaf3244444444444444455555543tttttttttttttttttttttdddddddddddddddddddddddddddddddddddddddddddddddddddddd";
    std::string  str2(str1);
    cout<<"str1对象地址="<<(long int )&str1<<"       str1C字符串地址"<<(long int )str1.c_str()<<endl;
    cout<<"str2对象地址="<<(long int )&str2<<"       str2C字符串地址"<<(long int )str2.c_str()<<endl;
    str2[0] = 'c';
    cout<<"修改操作之后======"<<endl;
    cout<<"str1对象地址="<<(long int )&str1<<"       str1C字符串地址"<<(long int )str1.c_str()<<endl;
    cout<<"str2对象地址="<<(long int )&str2<<"       str2C字符串地址"<<(long int )str2.c_str()<<endl;

    return 0;
}

运行执行修改操作的代码发现:
str1对象地址=140724647839328 str1C字符串地址6565928
str2对象地址=140724647839312 str2C字符串地址6565928
修改操作之后======
str1对象地址=140724647839328 str1C字符串地址6565928
str2对象地址=140724647839312 str2C字符串地址6566120
str2被重新分配了内存

补充一下关于__sso_string的内存分配原则:
通过追踪代码发现,会对比字符串长度是不是超过一个值,这个值就是_S_local_capacity 设定的初始值是15

    size_type __dnew = static_cast<size_type>(std::distance(__beg, __end));

    if (__dnew > size_type(_S_local_capacity))
      {
        _M_data(_M_create(__dnew, size_type(0)));
        _M_capacity(__dnew);
      }

enum { _S_local_capacity = 15 };
如果字符串长度超过15就会在堆上分配内存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值