2013-11-01 71 views
5

我在某些測驗中遇到了問題 「Is a string a vector? If yes, in what way? If no, why not?」 他們都有隨機訪問的內容。 但字符串有一些方法向量dosn`t.It也可能有引用計數。 所以很顯然,字符串不完全是一個向量(typedef字符串向量) 有沒有已知的實現class string : public vector <char>? 如果不是 - 那麼沒有實現它的原因是什麼?stl - 字符串是矢量嗎?

+0

字符串有一些方法向量dosn't?這是相反的。 –

+0

@MehdiTaxir - 例如c_str()或data()或find_first_of()等 – Yakov

+2

注意:C++ 11明確禁止引用計數的字符串 –

回答

6

從純哲學的角度來看:是的,一個字符串是一個類型的向量。它是一個存儲字符的連續內存塊(一個矢量是存儲任意類型對象的連續內存塊)。所以,從這個角度來看,一個字符串是一種特殊的矢量。

在設計和實施的std::stringstd::vector而言,它們共享一些相同的界面元素(如連續內存塊,operator[]),但std::string確實std::vector(側面說明派生:你不應該公開得出來自標準容器,因爲它們不是基於類的設計 - 例如它們沒有虛擬析構器),也不能直接相互轉換。也就是說,以下將無法編譯:

std::string s = "abc"; 
std::vector<char> v = s; // ERROR! 

然而,由於它們都具有迭代器的支持,您可以將字符串轉換爲一個向量:

std::string s = "abc"; 
std::vector<char> v(s.begin(), s.end()); // note that the vector will NOT include the '\0' character 

std::string將不再有引用計數(從C++ 11開始)作爲C-11標準禁止的許多實現所使用的寫時複製功能。

從存儲角度來看,std::string實例會顯得很相似std::vector<char>(例如,它們都將有一個指向其存儲位置,大小,容量),但是這兩個類的功能不同。

+0

「你不應該公開從標準容器中派生,因爲它們沒有虛擬析構函數」。嗯,我認爲這在很大程度上是真實的,但會掩蓋一點。我會在中間插入一些文本:「你不應該公開從標準容器中派生出來,因爲它們不是用來作爲基類的,它們的一個線索是它們沒有虛擬析構函數。」這不是唯一的原因,並不完全是一個原因。 – BoBTFish

+0

@BoBTFish好點。我會調整措辭。 –

+0

只是詞彙表上的一個nit,但一個vector不存儲類型,它存儲任意類型的對象。 (或多或少:例如,對象必須是可複製的。) –

10

std::stringstd::vector(和其他標準容器)具有相同的接口的非平凡部分,但它具有不同的目的是非常不同的事情。

它也可能實現得非常不同,因爲它允許像小字符串優化或寫時複製(自2011年以來不合法)之類的事情。 (雖然他們有可能有非常相似的實現)。

它們都支持隨機訪問迭代器,所以可以用類似的方式使用標準算法。 I 認爲std::string不能被分類爲序列容器。

這將是不可能直接通過從std::vector繼承實現許多的std::string的成員函數,因爲它隱藏的事實,這也被存儲NUL終止子。因此,當std::string::size返回3,std::vector::size將返回4,例如。 end和其他幾個也一樣。

3

沒有,std::stringstd::basic_string<char>),你可以把它的類型,包含char因爲它的股票與其他容器許多功能序列容器,但它的使用std::vector沒有實現。

3

它不能(或者至少肯定不應該)使用公有繼承來實現的主要原因是不應該允許從stringvector的隱式轉換。例如,如果我寫的代碼,如:

int f(std::vector<char> const &s); 

// ... 

std::string s; 
f(s); 

編譯應該失敗(缺少的f一些其他過載,接受一個string)。

如果你真的想,你可以(可能)使用私人繼承從std::vector合法實施的std::string雖然做。它可能不是那麼有效率,但至少是非正式的,我想不出明顯違反的要求。效率的損失是因爲std::vector需要更通用一些 - 它必須支持可以拋出異常的類型的實例化,而std::string僅用於通過類型來實例化,這些類型是免費的。

+0

無法使用公共繼承實現的另一個原因是缺少虛擬析構函數(對於任何std容器)。 –

+0

@ZacHowland好吧,我認爲繼承只是一個用戶不會知道的實現細節,所以他們永遠不會將'std :: vector *'存儲到'std :: string',當然也不會而不是刪除它。 – BoBTFish