🔥個人主頁: Forcible Bug Maker
🔥專欄: STL || C++
目錄
- 前言
- 🌈關于string類
- 🌈string類的成員函數
- 🔥默認成員函數
- ==string類對象的構造(constructor)==
- ==string類對象的析構==
- ==string類對象的賦值運算符重載==
- 🔥迭代器接口(iterators)
- ==begin==
- ==end==
- ==rbegin==
- ==rend==
- ==cbgin,cend,erbegin和crend==
- 結語
前言
本篇博客主要內容:STL庫中string類的默認成員函數和各種迭代器接口的介紹和使用。
在開始我們string類
使用接口的講解之前,想先講講為什么我們要學習string類。在C語言
中,字符串是以’\0’結尾的一些字符的集合,為了操作方便,C標準庫中提供了一些str系列的庫函數,但是這些庫函數與字符串是分離開的,不太符合OOP的思想,而且底層空間需要用戶自己管理,稍不留神可能還會越界訪問。
簡單說,string就是C++STL標準庫中便于維護和操作字符串的一個類。
學習STL過程中,我們主要參考這個網站中的文檔:https://cplusplus.com,雖然里面的內容是全英的,但是不用擔心,我會帶著大家一一去翻譯并講解其中的接口。
🌈關于string類
字符串是表示字符序列的類。
標準的字符串提供了此類對象的支持,其接口類似于標準字符容器的接口,但添加了專門用于操作單字節字符字符串的設計特性。
string類是basic_string模板類的一個實例,它使用char來實例化basic_string模板類,并用char_traits和allocator作為basic_string的默認參數(關于模板更多的信息,請參考basic_string)。
請注意,這個類獨立于所使用的編碼來處理字節:如果用來處理多字節或變長字符(如UTF-8)的序列,這個類的所有成員(如長度或大小)以及它的迭代器,將仍然按照字節(而不是實際編碼的字符)來操作。
對以上文字做一個總結:
string
是表示字符串的類- 該類的接口與常規容器的接口基本相同,再添加了一些專門用來操作string的常規操作。
string
類再底層實際是:basic_string
模板類的別名,typedef basic_string<char,char_traits,alloctor> string;
- 不能操作多字節或變長字節的序列。
在使用string類時,必須包含相應頭文件
#include<string>
以及using namespace std;
🌈string類的成員函數
C++STL庫的string類中重載的成員函數非常之多,但并不是每個接口都有著其必要性。string類是C++中最先被開發和實驗的類,由于向前兼容等各種原因,其實其中也不免存在一些函數的冗余,在上百個重載的接口中,真正常用的也就是那十幾二十個。對于一些相同道理的重載,我會做簡單解釋而不會展開講,避免文章內容的冗余。
🔥默認成員函數
string類對象的構造(constructor)
string類提供了七種方式的重載用于構造string類對象。
(1)無參構造(默認構造)
string();
構造出一個空的string,里面存儲0個字符元素。
(2)拷貝構造
string(const string& str);
構造出一個和str對象內容相同的拷貝對象。
(3)字串構造
string (const string& str, size_t pos, size_t len = npos);
拷貝str從pos位置開始跨越len個長度的元素到新創建的對象中(如果字符串太短或未提供第三個參數,直接從pos位置拷貝到字符串的末尾)。
(4)通過字符串構造
string (const char* s);
通過s指向的以 空字符(‘\0’) 結尾的字符串創建新的string類型的對象。
(5)通過部分字符串構造
string (const char* s, size_t n);
從s指向的字符串中拷貝前n個字符創建新的string類型的對象。
(6)字符填充構造
string (size_t n, char c);
用連續的n個c構成的串創建string類型的對象。
(7)迭代器區間構造
template <class InputIterator>
string (InputIterator first, InputIterator last);
通過迭代器區間 [first,last) 之間的元素,創建順序相同的新string對象。
你現在可能不知道迭代器是什么,不過你可以先將它理解成是一種指針,指向string中的元素,可以通過++或–來改變這種指針的指向。
使用樣例:
// string類的構造
#include <iostream>
#include <string>
// 由于下面使用了std::,所以此處不用命名空間展開
int main()
{std::string s0("Initial string");// constructors used in the same order as described above:std::string s1;std::string s2(s0);std::string s3(s0, 8, 3);std::string s4("A character sequence");std::string s5("Another character sequence", 12);std::string s6a(10, 'x');std::string s6b(10, 42); // 42是字符'*'的ASCII碼值std::string s7(s0.begin(), s0.begin() + 7);// 打印構造出來的字符串內容,這里重載了流插入>>和流提取<<運算符。std::cout << "s1: " << s1 << "\ns2: " << s2 << "\ns3: " << s3;std::cout << "\ns4: " << s4 << "\ns5: " << s5 << "\ns6a: " << s6a;std::cout << "\ns6b: " << s6b << "\ns7: " << s7 << '\n';return 0;
}
string類對象的析構
如你所見,析構只有一種,之前在類和對象篇已經講過了,析構函數是不能重載的。
析構函數編譯器會自動調用,釋放資源,所以就不需要你操心了。
string類對象的賦值運算符重載
string類提供了三種賦值運算符重載,用于給已經創建好的對象賦值。
(1)string對象賦值
string& operator=(const string& str);
將str的內容拷貝到被賦值的對象中。
返回值:被賦值對象(*this)的引用。
(2)字符串賦值
string& operator=(const char* s);
通過一個已有的字符串給string賦值,其實不重載此函數也可以達到效果(隱式類型轉換),但是考慮到隱式類型轉換是有效率損耗的,故標準庫中還是重載了此成員函數。
返回值:被賦值對象(*this)的引用。
(3)字符賦值
string& operator=(char c);
將字符直接賦值給串。
返回值:被賦值對象(*this)的引用。
使用樣例:
#include <iostream>
#include <string>
using namespace std;
int main()
{std::string str1, str2, str3;str1 = "Test string. "; // c-stringstr2 = str1; //stringstr3 = 'x'; //charcout << str1 << endl;cout << str2 << endl;cout << str3 << endl;return 0;
}
🔥迭代器接口(iterators)
什么是迭代器接口,就是成員函數返回迭代器的接口,也就是獲取迭代器的方法。
我們可以先將迭代器想象成指向容器元素的指針,而這些成員函數的作用就是讓我們獲取這些指針。同時我們可以通過+,-,++或–等運算符調整這種指針的指向。
begin
iterator begin();
const_iterator begin() const;
這兩個成員函數都返回一個指向string串中第一個元素的正向迭代器。
end
iterator end();
const_iterator end() const;
這兩個成員函數都返回一個指向string串中最后一個元素下一位的正向迭代器。
使用樣例:
// string::begin/end
#include <iostream>
#include <string>
using namespace std;
int main()
{std::string str("Test string");string::iterator it = str.begin();for (; it != str.end(); ++it)cout << *it;cout << endl;return 0;
}
string的迭代器(iterator)是一個定義在string類內部的一個類型,它能指向string對象的元素,而迭代器的對象可以通過string提供的成員函數獲取。上述代碼案例中的迭代器it被我們稱為正向迭代器,++使其向后移動指向下一元素,–使其向前移動指向上一元素。
而接下來我們要講的rbegin和rend,是獲取反向迭代器的兩個接口函數。
rbegin
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
這兩個成員函數都返回一個指向string串中最后一個元素的反向迭代器。
rend
reverse_iterator rend();
const_reverse_iterator rend() const;
這兩個成員函數都返回一個指向string串中第一個元素上一位的反向迭代器。
使用樣例:
// string::rbegin/rend
#include <iostream>
#include <string>
using namespace std;
int main()
{string str("now step live...");string::reverse_iterator rit = str.rbegin();for (; rit != str.rend(); ++rit)cout << *rit;cout << endl;return 0;
}
同理,string的反向迭代器(reverse_iterator)是一個定義在string類內部的一個類型,它能指向string對象的元素,而反向迭代器的對象可以通過string提供的成員函數獲取。反向迭代器,++使其向前移動指向上一元素,–使其后前移動指向下一元素。
cbgin,cend,erbegin和crend
這幾個作為C++11新增語法,專門提供了獲取const類型的四種迭代器接口,使迭代器可以讀,但不能通過迭代器解引用更改串中的內容。這里就不多做贅述。
結語
本篇博客講了關于string類構造的七種重載,賦值運算符的三種重載,以及各種string迭代器接口的使用。后面博主會繼續分享關于string類的使用以及STL更多的內容,感謝大家的支持。?