探索C++標準模板庫(STL):String接口實踐+底層的模擬實現(中篇)

?

前引:上一篇文章小編已經整理出了String的常用接口,梳理了各個接口的功能、參數,如何使用等各種實例。本篇文章將帶大家看看String這些接口的實踐使用,探索這些接口的實用性,是如何增加代碼效率的。在本篇文章的末尾,還奉上了部分底層的模擬實現,String類的使用是有趣的,下面我們來從實踐中感受String類帶給我們的快捷、效率!

目錄

string類的模擬實現

構造初始化

析構函數

流提取

流插入

大小比較

拷貝構造

賦值運算符重載


string類的模擬實現

下面我們來實現String的底層,解讀String的原理:

std庫里面的String有它的專屬空間,也就是C++庫

下面我們來命名自己的空間,同時String是一個類,我們需要實現:自定義空間+一個類

namespace Space
{class string{};
}
構造初始化

觀察庫里面的 string 初始化特點:

可以看到它的變量有三個:size、capacity、字符空間

下面我們來自己實現它的構造初始化:

初始化size、capacity、空間、存儲

//自定義構造
string(const char* allocator):_size(strlen(allocator)),_capacity(2*_size+1)
{try{_allocator = new char[_capacity];}catch (const exception& _allocator){cout << "空間開辟失敗" << endl;}//存儲strcpy(_allocator, allocator);
}

效果展示:

?可以看到是沒有問題的,但是我們平常是可能按下面的方式初始化的:

string S;

所以我們還得再寫一個無參默認構造,如下:

注意:不能是全缺省的,否則參數相同,編譯器無法區分

//默認構造
string():_size(0), _capacity(10)
{try{_allocator = new char[_capacity];}catch (const exception& _allocator){cout << "空間開辟失敗" << endl;}
}

以上我們的構造初始化就寫好了,可以隨時應對各種初始化情況,總代碼如下:

namespace Space
{class string{public://默認構造string():_size(0), _capacity(10){try{_allocator = new char[_capacity];}catch (const exception& _allocator){cout << "空間開辟失敗" << endl;}}//自定義構造string(const char* allocator):_size(strlen(allocator)),_capacity(2*_size+1){try{_allocator = new char[_capacity];}catch (const exception& _allocator){cout << "空間開辟失敗" << endl;}//存儲strcpy(_allocator, allocator);}private:size_t _size;size_t _capacity;char* _allocator;};
}
析構函數

這個函數很簡單,釋放空間,改變 size、capacity這些就可以了,如下:

//析構
~string()
{delete[]_allocator;_size = 0;_capacity = 0;cout << "釋放成功" << endl;
}
流提取

在上面我們已經實現了讀取函數,但是追求方便,且兩者有很大區別,比如:?

cout << S1.Read() << endl;
cout << S1 << endl;

ostream& operator<<(ostream& out, const string& _stl) //沒有找命名空間里面
{for (auto ac : _stl){cout << ac;}return out;
}

注意:不能在成員函數中實現,因為this指針會搶占第一個操作符位置,所以我們放在外面實現

區別:

C的字符數組,以\0為終止算長度

String不看\0,以size為終止長度,例如:

這樣看雖然沒有什么區別,但是如果添加上\0就有很大的變化了

可以看到流提取是不受\0影響的,所以我們需要注意這個點,字符的打印在流提取不受\0影響?

為什么流提取的實現需要以ostream&作為返回值

(1)允許多次連續提取

(2)避免流對象的開銷,規定直接傳引用

strcpy與memcpy的區別

特性strcpymemcpy
參數類型char*void*
終止條件遇到\0停止按指定字節數完成復制
長度控制自動計算顯式指定
數據安全高風險可控風險
適用場景純字符串操作任意內存數據復制

所以對于字符串我們需要根據形式區分二者的拷貝,否則會出很大的問題??

流插入

在模擬流插入時我們同樣要注意this指針的問題,因此需要在成員函數外面定義

我們看下面的問題:

注意(1):所以我們需要在輸入之前清理之前原本的字符,然后重置_size,效果如下:?

?注意(2):我們每次調用+=,都會開辟空間,效率可以優化,先存進數組里面,再最后統一拷? ? ? ? ? ? ? ? ? ? ? ? ?貝?

istream& operator>>(istream& in, string& _stl)
{//清理緩沖區_stl.clear();//輸入元素char c = in.get();//臨時數組int i = 0;char buff[128] = "\0";//直到c結束while (c != '\n' && c != '\0'){//先存入buff數組buff[i++] = c;//如果臨時數組滿了,就給_stlif (i == 127){memcpy(_stl._allocator, buff, i);//重置數組i = 0;}//_stl += c;//注意get會自動向后移動c = in.get();}//如果i沒有重置,說明沒有發生存滿if (i != 127){for (int j = 0; j < i; j++){//如果滿了就擴容if (_stl._size == _stl._capacity){_stl.reserve(2 * _stl._size);_stl._capacity = 2 * _stl._size;}//轉移到對象里面_stl._allocator[_stl._size++] = buff[j];}}return in;
}

效果展示:

大小比較

我們拿 > 舉例:大小比較我們一般采用的是運算符重載,里面根據當前字符的ASCII值比較

//大小比較
bool operator>(const string& S)const
{size_t p1 = 0, p2 = 0;//比較不同長度while (p1<_size && p2<S._size){if (_allocator[p1] == S._allocator[p2]){p1++;p2++;}else{if (_allocator[p1] > S._allocator[p2]){return true;}elsereturn false;}}//此時前面的字符都相等,但是沒有比較完if (p1 < _size){return true;}elsereturn false;return false;
}

效果展示:

拷貝構造

原理我就不說了,咱們直接實現:

//拷貝構造
string(const string& S)
{_allocator = new char[S._capacity];_size = S._size;_capacity = S._capacity;//數據拷貝memcpy(_allocator, S._allocator, S._capacity);
}
賦值運算符重載

將一個對象的內容賦給另一個對象,因為前面我們已經有了一定的了解,我們下面換一種玩法:

注意:如果沒有寫拷貝構造等,屬于淺拷貝,那么多次釋放同一個空間會出問題

我們知道swap可以交換任意形式的變量,所以我們先來實現一個可以交換對象的swap:

思路:先根據賦值對象A拷貝構造一個臨時對象B,然后把臨時對象B的數據給*this

void swap(const string& S)
{//先開辟空間,注意S出了swap函數會銷毀string tmp(S);//目的:創建一個臨時變量,把臨時變量的空間、大小等信息轉給Sstd:: swap(_allocator, tmp._allocator);std:: swap(_size, tmp._size);std:: swap(_capacity, tmp._capacity);
}

下面我們直接調用這個swap函數就OK了:

string& operator=(string& S)
{(*this).swap(S);return *this;
}

效果展示:

最后我們再梳理以下思路:

現在有兩個對象:A和B,我們的目標是A=B

進入swap函數先以B為模板調用拷貝構造出C,此時C是臨時對象,內容與B完全一致

然后將C的內容交換給A,C雖然會釋放,但是它在堆上開的內容只會main函數調用析構才會釋放

?

這里我們先完成構造、析構,由于排版問題,下一篇我們來完成它的功能結尾!

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??? 【霧非霧】期待與你的下次相遇!?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/81599.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/81599.shtml
英文地址,請注明出處:http://en.pswp.cn/web/81599.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【模型顯著性分析】配對樣本 t 檢驗

寫在前面&#xff1a;本博客僅作記錄學習之用&#xff0c;部分圖片來自網絡&#xff0c;如需引用請注明出處&#xff0c;同時如有侵犯您的權益&#xff0c;請聯系刪除&#xff01; 文章目錄 前言 t t t 檢驗配對樣本 t t t 檢驗&#xff08;適用于相關組&#xff09;代碼論文描…

商旅平臺排名:十大商旅服務平臺解析

商旅平臺排名&#xff1a;十大商旅服務平臺解析 在企業降本增效的關鍵轉型期&#xff0c;商旅管理正成為優化運營成本與提升管理效能的核心場景。如何在保障出行體驗的同時實現差旅成本精細化管控、管理流程智能化&#xff0c;成為越來越多企業的戰略焦點。隨著AI技術在數據洞…

題海拾貝:P1208 [USACO1.3] 混合牛奶 Mixing Milk

Hello大家好&#xff01;很高興我們又見面啦&#xff01;給生活添點passion&#xff0c;開始今天的編程之路&#xff01; 我的博客&#xff1a;<但凡. 我的專欄&#xff1a;《編程之路》、《數據結構與算法之美》、《題海拾貝》、《C修煉之路》 歡迎點贊&#xff0c;關注&am…

每天掌握一個Linux命令 - ab(Apache Benchmark)

Linux 命令工具 ab 使用指南 一、工具概述 ab&#xff08;Apache Benchmark&#xff09; 是 Apache 官方提供的開源壓力測試工具&#xff0c;用于衡量 Web 服務器的性能。它通過模擬多并發請求&#xff0c;測試服務器在高負載下的響應速度、吞吐量和穩定性&#xff0c;常用于…

AI的“空間盲癥“

<------最重要的是訂閱“魯班模錘”------> 當我們看到一張照片時&#xff0c;大腦會自動分析其中的空間關系——哪個物體在前&#xff0c;哪個在后&#xff0c;左邊是什么&#xff0c;右邊是什么。但對于當今最先進的AI系統來說&#xff0c;這種看似簡單的空間理解卻是…

數據擬合實驗

實驗類型&#xff1a;●驗證性實驗 ○綜合性實驗 ○設計性實驗 實驗目的: 進一步熟練掌握最小二乘多項式擬合算法&#xff0c;提高編程能力和解決擬合問題的實踐技能。 實驗內容&#xff1a; 1 對下列數據&#xff0c;求解最小二乘拋物線f(x)Ax2BxC x -3 -1 1 3 y 15 5 …

系統思考:心智模式與業務創新

在最近的項目交付討論中&#xff0c;我頻繁聽到一個詞&#xff1a;“缺合適的人”。這讓我陷入了深思&#xff1a;我們是否還在傳統的生產力概念&#xff1f;納瓦爾提出的三種杠桿&#xff1a;勞動力、資本、零邊際成本產品。在當今這個信息化、全球化的商業世界中&#xff0c;…

python分步合并處理excel數據

文章目錄 概要整體架構流程技術名詞解釋技術細節小結概要 客戶需求 1. 背景與目標 用戶需要將三個包含農業實驗數據的Excel表格(AK、AN、AP)合并為一個結構化數據集,用于后續分析。每個表格包含相同類型的字段(如對照組與PSB處理組的樣本數、均值、標準差),但需通過字…

Python爬蟲實戰:研究PyQuery庫相關技術

1. 引言 1.1 研究背景與意義 隨著互聯網的快速發展,網絡上的數據量呈爆炸式增長。如何高效地從海量的網頁數據中提取有價值的信息,成為當前信息技術領域的一個重要研究方向。網絡爬蟲作為一種自動獲取網頁內容的程序,能夠按照一定的規則,自動地抓取萬維網信息,在搜索引擎…

深度學習---注意力機制(Attention Mechanism)

一、核心概念與發展背景 注意力機制是深度學習中模擬人類注意力選擇能力的關鍵技術&#xff0c;旨在從海量信息中篩選關鍵特征&#xff0c;解決長序列信息處理中的瓶頸問題&#xff08;如RNN的梯度消失&#xff09;。其核心思想是&#xff1a;對輸入序列的不同部分分配不同權重…

Jenkins分配對應項目權限與用戶管理

在日常開發過程中經常會出現用戶和權限管理問題&#xff0c;沒有配置trigger時&#xff0c;通常需要我們手動構建&#xff0c;但此時前端和后端的朋友沒有build權限&#xff0c;導致每次dev環境測試都需要麻煩我們手動去構建&#xff0c;消息傳達不及時則會降低開發效率。 現有…

XCTF-web-file_include

解析 <?php highlight_file(__FILE__); // 高亮顯示當前PHP文件源代碼 include("./check.php"); // 包含檢查文件&#xff08;可能包含安全過濾邏輯&#xff09;if(isset($_GET[filename])) { // 檢查是否傳入filename參數$filename $_GET[f…

matlab全息技術中的菲涅爾仿真成像

matlab全息技術中的菲涅爾仿真成像程序。 傅里葉法&#xff08;重建距離得大&#xff09;/Fresnel.m , 545 傅里葉法&#xff08;重建距離得大&#xff09;/FresnelB.m , 548 傅里葉法&#xff08;重建距離得大&#xff09;/Fresnel_solution.m , 1643 傅里葉法&#xff08;重…

CS144 - LAB0

CS144 - Lab 0 telnet 發送請求 如圖&#xff0c;很簡單&#xff0c;但是注意輸入時間太久會超時 發郵箱 首先我們需要用命令行去發郵箱&#xff0c;這里我用企業微信郵箱給自己的 qq 郵箱發送~ 整個命令如下&#xff01; 對于其中的參數&#xff0c;其實從英文就可以看出來…

kafka SASL/PLAIN 認證及 ACL 權限控制

一、Zookeeper 配置 SASL/PLAIN 認證&#xff08;每個zookeeper節點都要做&#xff09; 1.1 在 zookeeper 的 conf 目錄下&#xff0c;創建 zk_server_jaas.conf 文件&#xff0c;內容如下 Server {org.apache.kafka.common.security.plain.PlainLoginModule requiredusernam…

20250528-C#知識:函數簡介及函數重載

C#知識&#xff1a;函數簡介及函數重載 本文主要介紹函數參數和函數重載相關的知識點 1、函數 函數一般寫在類中 一般函數調用 static int Add(int num, int value){num value;return num;}//一般函數調用&#xff0c;發生值類型參數的復制int num 1;Add(num, 1); //調用…

Vue內置指令與自定義指令

一、前言 在 Vue 開發中&#xff0c;指令&#xff08;Directives&#xff09; 是一種非常強大的特性&#xff0c;它允許我們以聲明式的方式操作 DOM。Vue 提供了一些常用的內置指令&#xff0c;如 v-if、v-show、v-bind、v-on 等&#xff0c;同時也支持開發者根據需求創建自己…

華為AP6050DN無線接入點瘦模式轉胖模式

引言 華為AP6050DN是一款企業級商用的無線接入點。由于產品定位原因,其默認工作在瘦模式下,即須經AC統一控制和管理,是不能直接充當普通的無線路由器來使用的。 而本文的目的,就是讓其能脫離AC的統一控制和管理,當作普通無線路由器來使用。 硬件準備 華為AP6050DN無線接…

程序員出海之英語-使用手冊

為什么現在實時翻譯工具這么牛逼了&#xff0c;AI轉譯這么準確了&#xff0c;我還在這里跟老古董一樣吭哧吭哧學英語呢&#xff1f; 這是因為我們始終是和人打交道&#xff0c;不僅僅是為了考試&#xff0c;看懂官方文章&#xff0c;聽懂官方視頻。這里為什么說官方&#xff0c…

Java 事務管理:在分布式系統中實現可靠的數據一致性

Java 事務管理&#xff1a;在分布式系統中實現可靠的數據一致性 在當今的軟件開發領域&#xff0c;分布式系統逐漸成為主流架構。然而&#xff0c;這也給事務管理帶來了巨大的挑戰。本文將深入探討 Java 事務管理在分布式系統中的關鍵要點&#xff0c;并通過詳細代碼實例展示如…