【C++】string类的底层

打印 上一主题 下一主题

主题 977|帖子 977|积分 2931

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
目录
1.经典的string类问题
2 .浅拷贝 
3.深拷贝
​编辑 3.1 传统版写法的String类
3.2 现代版写法的String类
4.string类模拟实现代码参考
5.写时拷贝


1.经典的string类问题

上一篇博客已经对string类进行了简朴的先容,各人只要可以或许正常使用即可。在面试中,面试官总喜好让门生自己来模拟实现string类,最告急是实现string类的构造、拷贝构造、赋值运算符重载以及析构函数。各人看下以下string类的实现是否有问题?
  1. // 为了和标准库区分,此处使用String
  2. class String
  3. {
  4. public:
  5.         /*String()
  6.         :_str(new char[1])
  7.         {*_str = '\0';}
  8.         */
  9.         //String(const char* str = "\0") 错误示范
  10.         //String(const char* str = nullptr) 错误示范
  11.         String(const char* str = "")
  12.         {
  13.                 // 构造String类对象时,如果传递nullptr指针,可以认为程序非
  14.                 if (nullptr == str)
  15.                 {
  16.                         assert(false);
  17.                         return;
  18.                 }
  19.                 _str = new char[strlen(str) + 1];
  20.                 strcpy(_str, str);
  21.         }
  22.         ~String()
  23.         {
  24.                 if (_str)
  25.                 {
  26.                         delete[] _str;
  27.                         _str = nullptr;
  28.                 }
  29.         }
  30. private:
  31.         char* _str;
  32. };
  33. // 测试
  34. void TestString()
  35. {
  36.         String s1("hello bit!!!");
  37.         String s2(s1);
  38. }
复制代码
 

   说明:上述String类没有显式定义其拷贝构造函数与赋值运算符重载,此时编译器会合成默认
的,当用s1构造s2时,编译器会调用默认的拷贝构造。最终导致的问题是,s1、s2共用同一块内存空间,在释放时同一块空间被释放多次而引起程序瓦解,这种拷贝方式,称为浅拷贝。
  2 .浅拷贝 

   浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,末了就会导致
多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该
资源已经被释放,以为另有用,所以当继承对资源进项操纵时,就会发生发生了访问违规。
  
就像一个家庭中有两个孩子,但父母只买了一份玩具,两个孩子愿意一块玩,则万事大吉,万一
不想分享就你争我夺,玩具损坏。 
可以采用深拷贝解决浅拷贝问题,即:每个对象都有一份独立的资源,不要和其他对象共享。父
母给每个孩子都买一份玩具,各自玩各自的就不会有问题了。
3.深拷贝

   
如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情况都是按照深拷贝方式提供。 
  
 3.1 传统版写法的String类


  1. class String
  2. {
  3. public:
  4.         String(const char* str = "")
  5.         {
  6.                 // 构造String类对象时,如果传递nullptr指针,可以认为程序非
  7.                 if (nullptr == str)
  8.                 {
  9.                         assert(false);
  10.                         return;
  11.                 }
  12.                 _str = new char[strlen(str) + 1];
  13.                 strcpy(_str, str);
  14.         }
  15.         String(const String& s)
  16.                 : _str(new char[strlen(s._str) + 1])
  17.         {
  18.                 strcpy(_str, s._str);
  19.         }
  20.         String& operator=(const String& s)
  21.         {
  22.                 if (this != &s)
  23.                 {
  24.                         char* pStr = new char[strlen(s._str) + 1];
  25.                         strcpy(pStr, s._str);
  26.                         delete[] _str;
  27.                         _str = pStr;
  28.                 }
  29.                 return *this;
  30.         }
  31.         ~String()
  32.         {
  33.                 if (_str)
  34.                 {
  35.                         delete[] _str;
  36.                         _str = nullptr;
  37.                 }
  38.         }
  39. private:
  40.         char* _str;
  41. };
复制代码
3.2 现代版写法的String类

  1. class String
  2. {
  3. public:
  4.         String(const char* str = "")
  5.         {
  6.                 if (nullptr == str)
  7.                 {
  8.                         assert(false);
  9.                         return;
  10.                 }
  11.                 _str = new char[strlen(str) + 1];
  12.                 strcpy(_str, str);
  13.         }
  14.         String(const String& s)
  15.                 : _str(nullptr)
  16.         {
  17.                 String strTmp(s._str);
  18.                 swap(_str, strTmp._str);
  19.         }
  20.         // 对比下和上面的赋值那个实现比较好?
  21.         String& operator=(String s)
  22.         {
  23.                 swap(_str, s._str);
  24.                 return *this;
  25.         }
  26.         /*
  27.         String& operator=(const String& s)
  28.         {
  29.         if(this != &s)
  30.         {
  31.         String strTmp(s);
  32.         swap(_str, strTmp._str);
  33.         }
  34.         return *this;
  35.         }
  36.         */
  37.         ~String()
  38.         {
  39.                 if (_str)
  40.                 {
  41.                         delete[] _str;
  42.                         _str = nullptr;
  43.                 }
  44.         }
  45. private:
  46.         char* _str;
  47. };
复制代码
4.string类模拟实现代码参考

string.h
  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #pragma once
  3. #include<iostream>
  4. #include<cstring>
  5. #include<assert.h>
  6. using namespace std;
  7. namespace LCL
  8. {
  9.         class string
  10.         {
  11.         public:
  12.                 friend         ostream& operator<<(ostream& os, const string& s);
  13.                 friend istream& operator>>(istream& is, string& s);
  14.                 friend istream& getline(istream& is, string& s, char delim);
  15.                 using iterator = char*;
  16.                 using const_iterator = const char*;
  17.                 string(const char* str = "");//这里不能给空
  18.                 string(const string& s);
  19.                 string& operator=(const string& s);
  20.                 ~string();
  21.                 char& operator[](size_t i)
  22.                 {
  23.                         assert(i < _size);
  24.                         return _str[i];
  25.                 }
  26.                 const char& operator[](size_t i) const
  27.                 {
  28.                         assert(i < _size);
  29.                         return _str[i];
  30.                 }
  31.                 size_t size() const
  32.                 {
  33.                         return _size;
  34.                 }
  35.                 const char* c_str() const
  36.                 {
  37.                         return _str;
  38.                 }
  39.                 iterator begin()
  40.                 {
  41.                         return _str;
  42.                 }
  43.                 iterator end()
  44.                 {
  45.                         return _str + _size;
  46.                 }
  47.                 const_iterator begin() const
  48.                 {
  49.                         return _str;
  50.                 }
  51.                 const_iterator end() const
  52.                 {
  53.                         return _str + _size;
  54.                 }
  55.                 void clear()
  56.                 {
  57.                         _str[0] = '\0';
  58.                         _size = 0;
  59.                 }
  60.                 void reserve(size_t n);//开空间
  61.                 void push_back(char ch);
  62.                 void append(const char* str);
  63.                 string& operator+=(char ch);
  64.                 string& operator+=(const char* str);
  65.                 void insert(size_t pos, char ch);
  66.                 void insert(size_t pos, const char* str);
  67.                 void erase(size_t pos, size_t len=npos);
  68.                 size_t find(char ch, size_t pos = 0);
  69.                 size_t find(const char* str, size_t pos = 0);
  70.                 string substr(size_t pos, size_t len = npos);
  71.                
  72.                 void swap(string& s);
  73.         private:
  74.                 char* _str;
  75.                 size_t _size;
  76.                 size_t _capacity;
  77.         public:
  78.                 //特殊处理 只有整形才可以
  79.          /*  static const size_t npos = -1;*/
  80.            static const size_t npos;
  81.         };
  82.         bool operator==(const string& lhs, const string& rhs);
  83.         bool operator!=(const string& lhs, const string& rhs);
  84.         bool operator>(const string& lhs, const string& rhs);
  85.         bool operator<(const string& lhs, const string& rhs);
  86.         bool operator<=(const string& lhs, const string& rhs);
  87.         bool operator>=(const string& lhs, const string& rhs);
  88.         ostream& operator<<(ostream& os, const string& s);
  89.         istream& operator>>(istream& is, string& s);
  90.         istream& getline(istream& is, string& s, char delim = '\n');
  91. }
复制代码
string.c 
  1. #include"string.h"
  2. namespace LCL
  3. {       
  4.         const size_t string::npos = -1;
  5.         string::string(const char* str)
  6.                 :_size(strlen(str))
  7.         {
  8.                 _capacity = _size;
  9.                 _str = new char[_size + 1];
  10.                 strcpy(_str, str);
  11.         }
  12.         //s2(s1)
  13.         //传统写法
  14.         //string::string(const string& s)
  15.         //{
  16.         //        _str = new char[s._capacity+1];
  17.         //        strcpy(_str, s._str);
  18.         //        _size = s._size;
  19.         //        _capacity = s._capacity;
  20.         //}
  21.         string::string(const string& s)
  22.         {
  23.                 string tmp(s._str);
  24.                 swap(tmp);
  25.         }
  26.         string& string::operator=(const string& s)
  27.         {
  28.                 if (this != &s)
  29.                 {
  30.                         delete[] _str;
  31.                         _str = new char[s._capacity + 1];
  32.                         strcpy(_str, s._str);
  33.                         _size = s._size;
  34.                         _capacity = s._capacity;
  35.                 }
  36.                 return *this;//为了连续赋值必须返回自身的引用
  37.         }
  38.         string::~string()
  39.         {
  40.                 delete[] _str;
  41.                 _str = nullptr;
  42.                 _size = _capacity = 0;
  43.         }
  44.         void string::reserve(size_t n)
  45.         {
  46.                 if (n > _capacity)
  47.                 {
  48.                         char* newstr = new char[n+1];//开空间永远要多开一个给'\0'留位置
  49.                         //把原来的数据拷过来
  50.                         strcpy(newstr, _str);
  51.                         delete[] _str;
  52.                         _str = newstr;
  53.                         _capacity = n;
  54.                 }
  55.         }
  56.         void string::push_back(char ch)
  57.         {
  58.                 if (_size == _capacity)
  59.                 {
  60.                         //扩容
  61.                         reserve(_capacity == 0 ? 4 : 2 * _capacity);
  62.                 }
  63.                 _str[_size] = ch;//插入
  64.                 _size++;
  65.                 _str[_size] = '\0';//防止溢出
  66.         }
  67.         void string::append(const char* str)
  68.         {
  69.                 size_t len = strlen(str);
  70.                 if (_size + len > _capacity)
  71.                 {
  72.                         //扩容
  73.                         size_t newcapacity = 2 * _capacity;
  74.                         //扩2倍不够,需要多少阔多少
  75.                         if (newcapacity < len+_size)
  76.                         {
  77.                                 newcapacity = len + _size;
  78.                         }
  79.                         reserve(newcapacity);
  80.                 }
  81.                 //插入
  82.                 strcpy(_str+_size, str);
  83.                 _size += len;
  84.         }
  85.         string& string::operator+=(char ch)
  86.         {
  87.                 push_back(ch);
  88.                 return *this;
  89.         }
  90.         string& string::operator+=(const char* str)
  91.         {
  92.                 append(str);
  93.                 return *this;
  94.         }
  95.         void string::insert(size_t pos, char ch)
  96.         {
  97.                 assert(pos <= _size);
  98.                 if (_size == _capacity)
  99.                 {
  100.                         //扩容
  101.                         reserve(_capacity == 0 ? 4 : 2 * _capacity);
  102.                 }
  103.                 //挪动pos后面的元素
  104.                 int end = _size;
  105.                 while (end >= (int)pos)
  106.                 {
  107.                         _str[end + 1] = _str[end];
  108.                         end--;
  109.                 }
  110.                 _str[pos] = ch;//插入
  111.                 _size++;//更新_size
  112.         }
  113.         void string::insert(size_t pos, const char* str)
  114.         {
  115.                 assert(pos <= _size);
  116.                 size_t len = strlen(str);
  117.                 if (_size + len > _capacity)
  118.                 {
  119.                         //扩容
  120.                         size_t newcapacity = 2 * _capacity;
  121.                         //扩2倍不够,需要多少阔多少
  122.                         if (newcapacity < len + _size)
  123.                         {
  124.                                 newcapacity = len + _size;
  125.                         }
  126.                         reserve(newcapacity);
  127.                 }
  128.                 size_t end = _size + len;
  129.                 while (end > pos+len-1)
  130.                 {
  131.                         _str[end] = _str[end - len];
  132.                         end--;
  133.                 }
  134.                 for (size_t i = 0; i < len; i++)
  135.                 {
  136.                         _str[pos + i] = str[i];
  137.                 }
  138.                 _size += len;
  139.         }
  140.         void string::erase(size_t pos, size_t len)
  141.         {
  142.                 assert(pos < _size);
  143.                 if (len >= _size - pos)
  144.                 {
  145.                         _str[pos] = '\0';
  146.                         _size = pos;
  147.                 }
  148.                 else
  149.                 {
  150.                         size_t end = pos + len;
  151.                         while (end<=_size)
  152.                         {
  153.                                 _str[end - len] = _str[end];
  154.                                 end++;
  155.                         }
  156.                         _size -= len;
  157.                 }
  158.         }
  159.         size_t string::find(char ch, size_t pos)
  160.         {
  161.                 assert(pos < _size);
  162.                 for (size_t i = pos; i < _size; i++)
  163.                 {
  164.                         if (ch == _str[i])
  165.                                 return i;
  166.                 }
  167.                 return npos;
  168.         }
  169.         size_t string::find(const char* str, size_t pos)
  170.         {
  171.                 assert(pos<_size);
  172.                 const char* ptr = strstr(_str + pos, str);
  173.                 if (ptr == nullptr)
  174.                 {
  175.                         return npos;
  176.                 }
  177.                 else
  178.                 {
  179.                         return ptr - _str;
  180.                 }
  181.         }
  182.         string string::substr(size_t pos, size_t len)
  183.         {
  184.                 assert(pos < _size);
  185.                 if (len > (_size - pos))
  186.                 {
  187.                         len = _size - pos;
  188.                 }
  189.                 string str;
  190.                 reserve(len);
  191.                 for (size_t i = 0; i < len; i++)
  192.                 {
  193.                         str += _str[pos + i];
  194.                 }
  195.                 return str;
  196.         }
  197.         bool operator==(const string& lhs, const string& rhs)
  198.         {
  199.                 return strcmp(lhs.c_str(), rhs.c_str()) == 0;
  200.         }
  201.         bool operator!=(const string& lhs, const string& rhs)
  202.         {
  203.                 return !(lhs == rhs);
  204.         }
  205.         bool operator>(const string& lhs, const string& rhs)
  206.         {
  207.                 return !(lhs <= rhs);
  208.         }
  209.         bool operator<(const string& lhs, const string& rhs)
  210.         {
  211.                 return strcmp(lhs.c_str(), rhs.c_str()) < 0;
  212.         }
  213.         bool operator<=(const string& lhs, const string& rhs)
  214.         {
  215.                 return lhs < rhs || lhs == rhs;
  216.         }
  217.         bool operator>=(const string& lhs, const string& rhs)
  218.         {
  219.                 return !(lhs < rhs);
  220.         }
  221.         ostream& operator<<(ostream& os, const string& s)
  222.         {
  223.                 for(size_t i = 0; i < s.size(); i++)
  224.                 {
  225.                         os << s[i];
  226.                 }
  227.                 return os;
  228.         }
  229.         istream& operator>>(istream& is, string& s)
  230.         {
  231.                 s.clear();
  232.                 int i = 0;
  233.                 char buffer[256];
  234.                 char ch;
  235.                 ch = is.get();
  236.                 while (ch != ' ' && ch != '\n')
  237.                 {
  238.                         buffer[i++] = ch;
  239.                         if (i == 255)
  240.                         {
  241.                                 buffer[i] = '\0';
  242.                                 s += buffer;
  243.                                 i = 0;
  244.                         }
  245.                         ch = is.get();
  246.                 }
  247.                 if (i > 0)
  248.                 {
  249.                         buffer[i] = '\0';
  250.                         s += buffer;
  251.                 }
  252.                 return is;
  253.         }
  254.         istream& getline(istream& is, string& s, char delim)
  255.         {
  256.                 s.clear();
  257.                 int i = 0;
  258.                 char buffer[256];
  259.                 char ch;
  260.                 ch = is.get();
  261.                 while (ch != delim)
  262.                 {
  263.                         buffer[i++] = ch;
  264.                         if (i == 255)
  265.                         {
  266.                                 buffer[i] = '\0';
  267.                                 s += buffer;
  268.                                 i = 0;
  269.                         }
  270.                         ch = is.get();
  271.                 }
  272.                 if (i > 0)
  273.                 {
  274.                         buffer[i] = '\0';
  275.                         s += buffer;
  276.                 }
  277.                 return is;
  278.         }
  279.         void string::swap(string& s)
  280.         {
  281.                 std::swap(_str, s._str);
  282.                 std::swap(_size, s._size );
  283.                 std::swap(_capacity, s._capacity);
  284.         }
  285. }
复制代码
测试:test.c
  1. #include"string.h"
  2. void testString01()
  3. {
  4.         LCL::string s1("hello world");
  5.         cout << s1.c_str() << endl;
  6.         s1 += ' ';
  7.         s1 += "hello bit";
  8.         cout << s1.c_str() << endl;
  9.         LCL::string s2("hello world");
  10.         s2.insert(0, 'a');
  11.         cout << s2.c_str() << endl;
  12.         LCL::string s3("hello world");
  13.         cout << s3.c_str() << endl;
  14.         s3.insert(0, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
  15.         cout << s3.c_str() << endl;
  16.         LCL::string s4("hello world");
  17.         s4.erase(5);
  18.         cout << s4.c_str() << endl;
  19. }
  20. void testString02()
  21. {
  22.         LCL::string s5("hello world");
  23.         cout << s5.find(' ') << endl;
  24.         cout << s5.find("world") << endl;
  25.         LCL::string s6 = "https://legacy.cplusplus.com/reference/string/string/?kw=string";
  26.         size_t pos1 = s6.find(':');
  27.         size_t pos2=s6.find('/', pos1 + 3);
  28.         if (pos1 != string::npos && pos2 != string::npos)
  29.         {
  30.                 LCL::string domain = s6.substr(pos1 + 3, pos2 - (pos1 + 3));
  31.                 cout << domain.c_str() << endl;
  32.         }
  33. }
  34. void testString03()
  35. {
  36.         LCL::string s1("hello world");
  37.         LCL::string s2(s1);
  38.         cout << s2.c_str() << endl;       
  39.         cout << (s1 == s2) << endl;
  40.         cout << (s1 < s2) << endl;
  41.         cout << ("hello world" == s1) << endl;
  42. }
  43. void testString04()
  44. {
  45.         //LCL::string s1="hhhhh";
  46.         //cin >> s1;
  47.         //cout << s1 << endl;
  48.         LCL::string s2;
  49.         getline(cin, s2,'#');
  50.         cout << s2 << endl;
  51.        
  52. }
  53. void testString05()
  54. {
  55.         LCL::string s1 = "llllll";
  56.         LCL::string s2 = "ccccccc";
  57.        
  58.         s1.swap(s2);
  59.         cout << s1 << endl;
  60.         cout << s2 << endl;
  61. }
  62. int main()
  63. {
  64.         //LCL::string s1("1111");
  65.         //cout << s1.c_str() << endl;
  66.         //LCL::string s2;
  67.         //cout << s2.c_str() << endl;
  68.         //LCL::string s3("1234");
  69.         //cout << s3.size() << endl;
  70.         //s3[0] = 'x';
  71.         //cout << s3.c_str() << endl;
  72.         //for (size_t i = 0; i < s3.size(); i++)
  73.         //{
  74.         //        cout << s3[i] << " ";
  75.         //}
  76.         //cout << endl;
  77.         //LCL::string::iterator it1 = s3.begin();
  78.         //while (it1!=s3.end())
  79.         //{
  80.         //        //*it1 = 'a';
  81.         //        cout << *it1 << " ";
  82.         //        it1++;
  83.         //}
  84.         //cout << endl;
  85.         范围for
  86.         支持迭代器就支持范围for
  87.         //for (auto e : s3)
  88.         //{
  89.         //        cout << e << " ";
  90.         //}
  91.         //cout << endl;
  92.         //const LCL::string s4("lllllll");
  93.         //cout << s4.size() << endl;       
  94.         //cout << s4[1] << endl;
  95.         //LCL::string::const_iterator it2 = s4.begin();
  96.         //while (it2!=s4.end())
  97.         //{
  98.         //        cout << *it2 << " ";
  99.         //        it2++;
  100.         //}
  101.         //cout << endl;
  102.         //for (auto a : s4)
  103.         //{
  104.         //        cout << a << " ";
  105.         //}
  106.         //cout << endl;
  107.         /*LCL::string s2("2");
  108.         cout << s2.c_str() << endl;*/
  109.         //s2 += '1';
  110.         //s2 += "33333";
  111.         //cout << s2.c_str() << endl;
  112.         //testString01();
  113.         //testString02();
  114.         //testString03();
  115.         //testString04();
  116.         testString05();
  117.         return 0;
  118. }
复制代码
5.写时拷贝

   
写时拷贝就是一种拖延症,是在浅拷贝的基础之上增加了引用计数的方式来实现的。
引用计数:用来记载资源使用者的个数。在构造时,将资源的计数给成1,每增加一个对象使用该资源,就给计数增加1,当某个对象被销毁时,先给该计数减1,然后再查抄是否需要释放资源,如果计数为1,说明该对象时资源的末了一个使用者,将该资源释放;否则就不能释放,因为另有其他对象在使用该资源。
  1. #include <iostream>
  2. #include <cstring>
  3. #include <atomic>
  4. class CowString {
  5. public:
  6.         // 默认构造函数
  7.         CowString() : data(nullptr), length(0), ref_count(new std::atomic<int>(1)) {}
  8.         // 构造函数,接受C风格字符串
  9.         CowString(const char* str) {
  10.                 if (str) {
  11.                         length = std::strlen(str);
  12.                         data = new char[length + 1];
  13.                         std::strcpy(data, str);
  14.                         ref_count = new std::atomic<int>(1);
  15.                 }
  16.                 else {
  17.                         data = nullptr;
  18.                         length = 0;
  19.                         ref_count = new std::atomic<int>(1);
  20.                 }
  21.         }
  22.         // 拷贝构造函数
  23.         CowString(const CowString& other) : data(other.data), length(other.length), ref_count(other.ref_count) {
  24.                 (*ref_count)++; // 增加引用计数
  25.         }
  26.         // 移动构造函数
  27.         CowString(CowString&& other) noexcept : data(other.data), length(other.length), ref_count(other.ref_count) {
  28.                 other.data = nullptr;
  29.                 other.length = 0;
  30.                 other.ref_count = new std::atomic<int>(1); // 重置移动后的对象为独立状态
  31.         }
  32.         // 析构函数
  33.         ~CowString() {
  34.                 if (data && --(*ref_count) == 0) { // 当引用计数为零时释放内存
  35.                         delete[] data;
  36.                         delete ref_count;
  37.                 }
  38.         }
  39.         // 赋值运算符
  40.         CowString& operator=(const CowString& other) {
  41.                 if (this != &other) { // 防止自我赋值
  42.                         CowString temp(other); // 使用拷贝构造函数创建临时对象
  43.                         std::swap(data, temp.data);
  44.                         std::swap(length, temp.length);
  45.                         std::swap(ref_count, temp.ref_count);
  46.                 }
  47.                 return *this;
  48.         }
  49.         // 移动赋值运算符
  50.         CowString& operator=(CowString&& other) noexcept {
  51.                 if (this != &other) {
  52.                         delete[] data; // 释放当前数据(如果存在)
  53.                         data = other.data;
  54.                         length = other.length;
  55.                         ref_count = other.ref_count;
  56.                         // 重置移动后的对象为独立状态
  57.                         other.data = nullptr;
  58.                         other.length = 0;
  59.                         other.ref_count = new std::atomic<int>(1);
  60.                 }
  61.                 return *this;
  62.         }
  63.         // 获取C风格字符串
  64.         const char* c_str() const {
  65.                 return data;
  66.         }
  67.         // 获取字符串长度
  68.         size_t size() const {
  69.                 return length;
  70.         }
  71.         // ... 其他成员函数(如operator+,substr等)可以按需添加 ...
  72. private:
  73.         char* data; // 字符数据
  74.         size_t length; // 字符串长度
  75.         std::atomic<int>* ref_count; // 引用计数(使用原子操作以保证线程安全)
  76. };
  77. int main() {
  78.         CowString str1("Hello, World!");
  79.         CowString str2 = str1; // 使用拷贝构造函数
  80.         std::cout << "str1: " << str1.c_str() << std::endl;
  81.         std::cout << "str2: " << str2.c_str() << std::endl;
  82.         // 在这里,str1和str2共享相同的数据
  83.         // 修改str1会导致数据拷贝
  84.         char* temp = new char[str1.size() + 1];
  85.         std::strcpy(temp, str1.c_str());
  86.         temp[5] = 'C++'; // 修改拷贝的数据以避免未定义行为(不能直接修改共享数据)
  87.         // 注意:下面的操作是错误的,因为它直接修改了共享的数据,这在实际COW实现中是不允许的。
  88.         // 为了演示,我们暂时这样做,但在真正的COW实现中,你应该先执行深拷贝再修改。
  89.         // data[5] = 'C'; // 错误!这将直接修改str1和str2共享的数据。
  90.         // 正确的做法是先深拷贝再修改(这里只是演示,所以跳过深拷贝步骤)
  91.         // CowString str1_copy = str1; // 深拷贝
  92.         // str1_copy.data[5] = 'C'; // 修改深拷贝后的数据
  93.         // 由于我们直接修改了共享数据(上面的错误做法),下面的输出将是不确定的。
  94.         // 在真正的COW实现中,你应该避免这种情况。
  95.         std::cout << "After incorrect modification: " << std::endl;
  96.         std::cout << "str1: " << str1.c_str() << std::endl; // 输出可能是不确定的
  97.         std::cout << "str2: " << str2.c_str() << std::endl; // 输出可能是不确定的
  98.         // 清理内存(在main函数结束时,所有CowString对象都会被销毁,并释放内存)
  99.         delete[] temp;
  100.         return 0;
  101. }
  102. // 注意:上面的代码包含了一个错误示例,即直接修改共享数据。
  103. // 在真正的COW实现中,你应该在修改前检查引用计数,并在需要时进行深拷贝。
  104. // 此外,上面的代码没有实现完整的COW字符串类,比如缺少对operator+等的支持。
  105. // 这个示例仅用于教学目的,展示了COW的基本概念。
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

万万哇

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表