C++ Core Guidelines 筆記01

CppCoreGuidelines

由C++原作者發起的一個modern C++ guidelilne. 在這裏,配套的github頁面在這裏

CppCoreGuidelines 配套一組 Guideline Support Library,源碼位於這裏

我只記錄了對自己有啓發的內容。筆記中的大部分代碼片段是複製於原文,我自己增加的代碼片段會標註清楚。

P.1 Express ideas directly in code.

class Date {
public:
    Month month() const;  // do
    int month();          // don't
    // ...
};

所以,推薦的做法是利用type對所有可能的概念進行建模。例如不用一個primitive類型int來表示月份,而用一個專門的Month類。但是這樣做需要實現Month的一些運算用的接口,例如加法,減法。

change_speed(Speed s);    // better: the meaning of s is specified
// ...
change_speed(2.3);        // error: no unit
change_speed(23m / 10s);  // meters per second

這裏推薦我們實際使用value literal,也就是像23m,10s一樣的實現。

P.1 tips

使用gsl::index而不是int

P.3 Express intent

我理解的是在一段scope的開始,或者開始階段,最好能夠儘可能的指明接下來一段scope要進行的事。
不推薦的示例->

gsl::index i = 0;
while (i < v.size()) {
    // ... do something with v[i] ...
}

原文認爲i在scope外,沒有必要。只看while的開頭部分,沒有對接下來要發生的循環提供更多信息。循環是爲了做和v無關的事,還是要訪問v,修改v?下面的代碼有略微清楚的intent:我們要訪問v中的所有元素,但不修改這些元素。
推薦的示例->

for (const auto& x : v) { /* do something with the value of x */ }

也可以嘗試使用for_each

對於參數列表,有點類似於 P.1 ,定義專門的類。

draw_line(int, int, int, int);  // obscure
draw_line(Point, Point);        // clearer

原文強調,如果發生如下情況,很可能是函數設計的不夠好。
functions with many parameters of built-in types

P3 and P5 tips

使用gsl中的span來代替指針和size的組合。

void read(span<int> r); // read into the range of integers r

int a[100];
read(a);        // better: let the compiler figure out the number of elements

P.6 What cannot be checked at compile time should be checkable at run time

extern void f4(vector<int>&);   // separately compiled, possibly dynamically loaded
extern void f4(span<int>);      // separately compiled, possibly dynamically loaded
                                // NB: this assumes the calling code is ABI-compatible, using a
                                // compatible C++ compiler and the same stdlib implementation

void g3(int n)
{
    vector<int> v(n);
    f4(v);                     // pass a reference, retain ownership
    f4(span<int>{v});          // pass a view, retain ownership
}

原文說上述示例至少讓f4有check範圍(size or boundness)的可能。
下面代碼是兩個例子拼成的。

void increment2(span<int> p)
{
    for (int& x : p) ++x;
}

void use3(int m)
{
    const int n = 10;
    int a[n] = {};
    // ...
    increment2(a);   // the number of elements of a need not be repeated
    // ...
}

此時increment2有能力進行範圍檢查,use3不會因爲混淆n和m造成問題。

P.9 Don’t waste time or space

這裏的示例沒有解釋特別細緻。我理解到的指導意見是需要local copy時,儘量不要使用new delete pair,這在其他guideline裏也有提到。但是這並不是因爲效率問題,應該是爲了防止leak。原文提到了struct內部變量聲明的次序會引起空間浪費,這個在以前看到過但是並不記得正確的處理方法,一下也查不到其他guideline。

不要像下述代碼片段一樣在for循環中使用類似size()的函數除非size()真的會返回變化的數值。

void lower(zstring s)
{
    for (int i = 0; i < strlen(s); ++i) s[i] = tolower(s[i]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章