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]);
}