muduo::StringPiece?
在學習muduo的源碼,這個類的源碼是這樣的,
這兩個函數理解的不是很清楚,為什麼不驗證ptr這個指針指向的字元串長度呢?
class StringPiece
{
private:
const char* ptr_;
int length_;
public:
StringPiece() : ptr_(NULL), length_(0) { }
StringPiece(const char* str): ptr_(str), length_(static_cast&(strlen(ptr_))) { }
StringPiece(const unsigned char* str): ptr_(reinterpret_cast&(str)),length_(static_cast& (strlen(ptr_))) { }
StringPiece(const std::string str) : ptr_(str.data()), length_(static_cast&(str.size())) { }
StringPiece(const char* offset, int len) : ptr_(offset), length_(len) { }
const char* data() const { return ptr_; }
int size() const { return length_; }
bool empty() const { return length_ == 0; }
const char* begin() const { return ptr_; }
const char* end() const { return ptr_ + length_; }
void clear() { ptr_ = NULL; length_ = 0; }
void set(const char* buffer, int len) { ptr_ = buffer; length_ = len; }
void set(const char* str) { ptr_ = str; length_ = static_cast&(strlen(str)); }
void set(const void* buffer, int len) { ptr_ = reinterpret_cast&(buffer); length_ = len; }
char operator[](int i) const { return ptr_[i]; }
void remove_prefix(int n) { ptr_ += n; length_ -= n; }
void remove_suffix(int n) { length_ -= n; }
bool operator==(const StringPiece x) const { return ((length_ == x.length_) (memcmp(ptr_, x.ptr_, length_) == 0)); }
bool operator!=(const StringPiece x) const { return !(*this == x); }
std::string as_string() const { return std::string(data(), size());}
void CopyToStdString(std::string* target) const { target-&>assign(ptr_, length_); }
bool starts_with(const StringPiece x) const { return ((length_ &>= x.length_) (memcmp(ptr_, x.ptr_, x.length_) == 0)); }
int compare(const StringPiece x) const
{
int r = memcmp(ptr_, x.ptr_, length_ &< x.length_ ? length_ : x.length_); if (r == 0) { if (length_ &< x.length_) r = -1; else if (length_ &> x.length_) r = +1;
}
return r;
}
remove_suffix為什麼僅僅只是改變了長度,沒有將末尾填寫成" "呢?
void remove_prefix(int n) { ptr_ += n; length_ -= n; }void remove_suffix(int n) { length_ -= n; }是不是有更深層次的考慮?
就是string view
這個類實際上只是對字元串的一個proxy類而已(即設計模式中的代理模式),通常叫做string view.它提供了一個窗口,外部僅可以觀察到這個窗口中字元串的內容,在調整窗口大小時不需要修改原字元串,僅移動開始指針和調整長度即可。另外這個類自身並不存儲這個字元串,所以它的有效生存期取決於源字元串指針的生存期。
好的,現在看題主的問題:
1. 這兩個函數理解的不是很清楚,為什麼不驗證ptr這個指針指向的字元串長度呢?長度是由length來控制的。2. remove_suffix為什麼僅僅只是改變了長度,沒有將末尾填寫成" "呢?
現在假設我們有這樣一個初始字元串"abcde",它的窗口為[0, length),其中length = 5。那麼如果我們想去掉"ab"這兩個前置字元怎麼辦呢?注意我們是一個代理類,不需要去操作源串,只需要修改ptr_指針,讓它前進兩格就可以了。但是前進之後,長度變短了,這時需要把length_減去n;這時的窗口為[2, length)那如果是想去掉"de"呢?只需要把length_減去n就好了。這時的窗口為[0, length - 2)void remove_prefix(int n) { ptr_ += n; length_ -= n; }
void remove_suffix(int n) { length_ -= n; }所以題主應該看出來了,這樣的字元串不可能是以" "作為結束符的。它有獨立的length_來保證長度,同時,operator ==等函數的行為也保證了它只以length_作為終止的判斷。
回到原來的代碼上。
這段代碼可能有如下問題:
1. remove_prefix和remove_suffix都有可能把length_減成負值。這時候最好assert一下以防萬一。因為memcmp()的第三個參數是unsigned int型的,負值可能會變成一個很大的正值導致出錯。同時ptr也有可能會移出合法的內存區。2. 另外個人覺得length最好用size_t類型保存。3. CopyToStdString函數中先assert(target != nullptr);可能好些。我自己的習慣是CopyToStdString(std::string target); 直接用引用。不過據說某公司(從群里聽聞的)有傳修改的值用指針,傳const值用const引用的規定。-_-!應該是類似於 Boost.Utility 中的 string_ref 的東東。
首先搞清為什麼要有這個類
C++裡面有string和char*,如果你用const string s 做函數形參,可以同時兼容兩種字元串。但當你傳入一個很長的char * 時,會生成一個較大的string對象,開銷比較大。如果你的目的僅僅是讀取字元串的值,用這個StringPiece的話,僅僅是4+一個指針的內存開銷,而且也保證了兼容性。所以這個類的目的是傳入字元串的字面值,它內部的ptr_ 這塊內存不歸他所有。所以不能做任何改動。
另外這裡的ptr_也聲明為const,這也作者的本意就是只讀。// Taken from PCRE pcre_stringpiece.h
//
// Copyright (c) 2005, Google Inc.
// All rights reserved.
//
// Author: Sanjay Ghemawat
//
// A string like object that points into another piece of memory.
// Useful for providing an interface that allows clients to easily
// pass in either a "const char*" or a "string".
//
不懂。感覺這個類是個私用的類。
意思就是說這不是一個0結尾的字元串吧。有很多語言也是這樣的,譬如Pascal、Delphi、C#,還有COM的ABI什麼的。
const char* ptr_; 沒法修改
應該是出於性能考慮,將驗證工作交由調用者處理,至於為什麼不設置成0,看這個類的構造函數都是const類型,應該是該類只用於提取,而不用於修改
推薦閱讀:
※嵌入式這行業是不是不行了?
※使用sprintf時溢出怎麼會影響到變數的值?
※小弟做c++伺服器差不多一年了,用ace框架的,還沒什麼信心,還很菜,請教各位大神如何提升進階啊?
※計算機專業C++應該怎麼教?
※計算機中缺失MSVCP120D.dll和MSVCR120D.dll怎麼解決?