前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >std::string的拷贝赋值研究

std::string的拷贝赋值研究

作者头像
一见
发布2019-03-20 09:38:32
3.3K0
发布2019-03-20 09:38:32
举报
文章被收录于专栏:蓝天蓝天

说明:以下涉及的std::string的源代码摘自4.8.2版本。 结论:std::string的拷贝复制是基于引用计数的浅拷贝,因此它们指向相同的数据地址。 // std::string类定义 typedef basic_string string; template class basic_string { private:     // _Alloc_hider是模板类basic_string内嵌struct     struct _Alloc_hider : _Alloc     {         //  唯一构造函数,         // 在构造时使用第一个参数__dat初始化_M_p         _Alloc_hider(_CharT* __dat, const _Alloc& __a)             : _Alloc(__a), _M_p(__dat)        {}         // _M_p为实际存储数据的地方         _CharT* _M_p; // The actual data.     }; private:     _CharT* _M_data() const     { return  _M_dataplus._M_p; }     // 浅拷贝,     // 这正是x2=x1后,两者数据地址相同的原因     _CharT* _M_data(_CharT* __p)     { return (_M_dataplus._M_p = __p); }     _Rep* _M_rep() const     {         // 这里数组下标是“-1”         return &((reinterpret_cast<_Rep*>(_M_data()))[-1]);     }     // 维护引用计数     struct _Rep_base     {         size_type _M_length;         size_type _M_capacity;         _Atomic_word _M_refcount;     };     // _Rep是模板类basic_string内嵌struct     struct _Rep : _Rep_base     {         // The following storage is init'd to 0 by the linker,          // resulting (carefully) in an empty string with one reference.         // 空的std::string实际都指向了_S_empty_rep_storage,         // 因此它们的数据地址是相同的         static size_type _S_empty_rep_storage[];         static _Rep& _S_empty_rep()         {             void* __p = reinterpret_cast(&_S_empty_rep_storage);             return *reinterpret_cast<_Rep*>(__p);         }         _CharT* _M_grab(const _Alloc& __alloc1, const _Alloc& __alloc2)         {           return (!_M_is_leaked() && __alloc1 == __alloc2)                   ? _M_refcopy() : _M_clone(__alloc1);         }         _CharT* _M_refcopy() throw()         {         #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0             if (__builtin_expect(this != &_S_empty_rep(), false))         #endif             __gnu_cxx::__atomic_add_dispatch(&this->_M_refcount, 1);             return _M_refdata();         }  // XXX MT         _CharT* _M_refdata() throw()         { return reinterpret_cast<_CharT*>(this + 1); }     }; public:     static _Rep& _S_empty_rep()     {         return _Rep::_S_empty_rep();     }     // 不带参数的默认构造函数     // 测试环境_GLIBCXX_FULLY_DYNAMIC_STRING值为0,     // 因此只需要关注_S_empty_rep     basic_string() #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0         : _M_dataplus(_S_empty_rep()._M_refdata(), _Alloc())         { } #else         : _M_dataplus(_S_construct(size_type(), _CharT(), _Alloc()), _Alloc())         { } #endif     basic_string& assign(const basic_string& __str)     {         // 如果已经相同,则什么也不用做         if (_M_rep() != __str._M_rep())         {             const allocator_type __a = this->get_allocator();             _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());             _M_rep()->_M_dispose(__a);             _M_data(__tmp);         }         return *this;     } #if __cplusplus >= 201103L     basic_string& assign(basic_string&& __str)     {         this->swap(__str);         return *this;     } #endif // C++11     basic_string& operator=(const basic_string& __str)     {          return this->assign(__str);      } private:     // mutable表明const成员函数会修改_M_dataplus     mutable _Alloc_hider _M_dataplus; }; // 测试代码 // 编译命令: // g++ -g -o x x.cpp -D_GLIBCXX_DEBUG #include #include // 如果没有为结构X提供赋值函数, // 则编译器生成按位的赋值函数 struct X {     std::string str; }; int main() {     struct X x1, x2;     x1.str = "abc";     // X2指向的_S_empty_rep_storage     printf("%p, %p\n", x1.str.c_str(), x2.str.c_str());     // (gdb) p x1.str._M_dataplus._M_p     // (gdb) p x2.str._M_dataplus._M_p     // 拷贝赋值函数采用的是引用计数,     // 所以x1和x2的数据地址是相同的     x2 = x1;     printf("%p, %p\n", x1.str.c_str(), x2.str.c_str());     // 下面输出的x1和x2数据地址必然不同     x2.str = "123";     printf("%p, %p\n", x1.str.c_str(), x2.str.c_str());     return 0; }

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-03-14 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档