某日二師兄參加XXX科技公司的C++工程師開發崗位第18面:
面試官:
std::string用過吧?二師兄:當然用過(廢話,C++程式員就沒有沒用過
std::string的),面試官:
std::string("hello")+"world"、"hello"+std::string("world")和std::string("hello")+std::string("world")的結果是什么?為什么?二師兄:前者和后者的結果都是
std::string的物件,內容是“helloworld\0”,而中間的這個運算式無法通過編譯,原因是std::string多載了operator+(const char*)和operator+(const std::string&),但是const char*卻沒有多載operator+運算子,面試官:
std::string有兩個API,resize和reserve,你知道它們之間的區別嗎?二師兄:
resize對應的是size,resize可以改變字串的大小,reserve對應的是capacity,reserve只能改變capacity的大小,二師兄:當
resize傳入的引數小于字串的szie時,多余的字串會被截取,當reserve傳入的引數小于capacity時,reserve什么也不會做,二師兄:當
resize傳入的引數大于字串的szie時,增加的字串會被默認初始化,當reserve傳入的引數大于capacity時,capacity會被擴容,面試官:好的,可以通過下標訪問
std::string實體的內容嗎?二師兄:可以的,
std::string多載了下標運算子,可以像陣列一樣通過下標運算取出某個字符,面試官:你知道
std::string的at成員方法嗎?二師兄: 嗯,和下標運算功能相似,不過不用擔心越界問題,可以安全的訪問字串中的字符,
面試官:既然有
at方法了,為什么還要多載下標運算子呢?二師兄:主要是因為性能上的考量,
at雖然保證了不會超出字串范圍(超出范圍拋出例外),但是性能低于下標操作,這就是有舍有得,為了安全使用at,為了性能使用下標操作,C++給了你多個選擇,如何選擇看你的需求,面試官:那你知道
std::string是如何實作的嗎?二師兄:在
string內部維護一個指標,這個指標指向真正的字串的位置,面試官:能簡單的寫一下實作代碼嗎?
二師兄:好的,
class string
{
public:
string():size_(0),data_(nullptr){}
explicit string(const char* c)
{
size_ = strlen(c);
data_ = (char*)malloc(size_+1);
memset(data_,0,size_+1);
memcpy(data_,c,size_);
}
size_t size() const {return size_;}
const char* c_str() const {return data_;}
private:
size_t size_;
char* data_;
};
二師兄:在實作
append或者+=的時候,需要把當前字符的長度加上append的內容的長度,以此長度申請一塊新記憶體,然后把當前字串的記憶體和append的內容考入新申請的記憶體中,free掉之前data_指向的記憶體,然后把data_指標指向新申請的記憶體,面試官:好的,這樣的實作有一些弊端,如果頻繁的對一個
std::string物件append內容,會發生什么?二師兄:是的,因為頻繁的
malloc和free,會有性能問題,因所以編譯器在實作std::string的時候一般會預先申請一塊大的記憶體,這塊記憶體的長度是capacity,當添加的字串的長度加上當前的字串長度小于capacity時,直接添加到當前的塊上即可,面試官:好的,針對字串比較少的情況,一般編譯器會做一些優化,你知道如何優化的嗎?
二師兄:這個好像在哪看過,不記得額,,,
面試官:好的,今天的面試結束了,請回去等通知吧,
今天二師兄的表現不錯,除了最后一個問題,基本上都答上來了,讓我們來看下這個問題:
針對字串比較少的情況,一般編譯器會做一些優化,你知道如何優化的嗎?
我們可以看看GCC中std::string的實作:
typedef basic_string<char> string;
_Alloc_hider _M_dataplus;
size_type _M_string_length;
enum { _S_local_capacity = 15 / sizeof(_CharT) };
union
{
_CharT _M_local_buf[_S_local_capacity + 1];
size_type _M_allocated_capacity;
};
這里的_CharT就是char,所以_S_local_capacity等于15,當字串的長度小于等于15時,直接存在_M_local_buf中,而不需要在堆中申請記憶體,當字串長度大于15時,在記憶體中申請一塊記憶體,這塊記憶體的起始地址保存在_M_dataplus中,這塊記憶體的容量保存在_M_allocated_capacity 中,而字串的真實長度保存在_M_string_length中,當向字串中添加字符時,如果添加字符的長度大于 _M_allocated_capacity - _M_string_length,則需要resize,否則直接追加到_M_dataplus保存的記憶體塊中即可,
好了,今天的面試到這里就結束了,感謝小伙伴們的耐心閱讀,咱們明天繼續二師兄的面試之旅!
關注我,帶你21天“精通”C++!(狗頭)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/555499.html
標籤:其他
下一篇:返回列表
