天天看點

C++核心準則邊譯邊學-P.9 不要浪費時間和空間

P.9: Don't waste time or space(不要浪費時間和空間)

Reason(原因)

This is C++.

我們在用C++。

譯者注:之是以選擇C++而不是其他語言,就是希望使用最小的記憶體,獲得更快的性能。沒有道理不考慮時間和空間。

Note(注意)

Time and space that you spend well to achieve a goal (e.g., speed of development, resource safety, or simplification of testing) is not wasted. "Another benefit of striving for efficiency is that the process forces you to understand the problem in more depth." - Alex Stepanov

為達成目的而正确利用時間和空間(為了提高開發速度,資源安全,簡化測試等)不是浪費。“努力提高效率的另一個好處是這個過程會促使你在更深層次上了解問題。”-亞曆山大 斯特潘諾夫(STL之父)

Example, bad(反面示例)

struct X {    char ch;    int i;    string s;    char ch2;
    X& operator=(const X& a);    X(const X&);};
X waste(const char* p){    if (!p) throw Nullptr_error{};    int n = strlen(p);    auto buf = new char[n];    if (!buf) throw Allocation_error{};    for (int i = 0; i < n; ++i) buf[i] = p[i];    // ... manipulate buffer ...    X x;    x.ch = 'a';    x.s = string(n);    // give x.s space for *p    for (gsl::index i = 0; i < x.s.size(); ++i) x.s[i] = buf[i];  // copy buf into x.s    delete[] buf;    return x;}
void driver(){    X x = waste("Typical argument");    // ...}      

Yes, this is a caricature, but we have seen every individual mistake in production code, and worse. Note that the layout of ​

​X​

​​ guarantees that at least 6 bytes (and most likely more) are wasted. The spurious definition of copy operations disables move semantics so that the return operation is slow (please note that the Return Value Optimization, RVO, is not guaranteed here). The use of ​

​new​

​​ and ​

​delete​

​​ for ​

​buf​

​​ is redundant; if we really needed a local string, we should use a local ​

​string​

​. There are several more performance bugs and gratuitous complication.

是的,這個例子有點誇張,但是我在産品級代碼中看到過所有特别的錯誤,甚至更糟。注意X的記憶體結構中至少有6個位元組(很有可能更多)是多餘的。這個關于copy操作的假想定義禁止了移動文法,是以傳回操作會慢(請注意這裡沒有保證RVO,即傳回值優化)。buffer的new和delete操作是多餘的;如果确實需要局部字元串,我們應該使用局部的string對象。這裡還有幾個性能方面的問題和無謂的并發症。

譯者注:傳回值優化(RVO)的目的在于函數在傳回對象時減少必要的拷貝和構造動作,具體可以參照一下連接配接:

​​https://www.ibm.com/developerworks/community/blogs/5894415f-be62-4bc0-81c5-3956e82276f3/entry/RVO_V_S_std_move?lang=en​​

Example, bad(反面示例)

void lower(zstring s){    for (int i = 0; i < strlen(s); ++i) s[i] = tolower(s[i]);}      

This is actually an example from production code. We can see that in our condition we have ​

​i < strlen(s)​

​​. This expression will be evaluated on every iteration of the loop, which means that ​

​strlen​

​​ must walk through string every loop to discover its length. While the string contents are changing, it's assumed that ​

​toLower​

​ will not affect the length of the string, so it's better to cache the length outside the loop and not incur that cost each iteration.

這是一段來源于産品代碼的實際的例子。我們可以看到i<strlen(s)的循環條件。這個表達式會在每次循環疊代時被計算,這意味着strlen必須每次疊代都周遊一次字元串以擷取長度。當字元串的内容被修改時,我們可以認為toLower操作不會影響字元串長度,是以較好的做法是在循環外緩存字元串的長度而不必每次疊代都付出那麼大的代碼。

Note(注意)

An individual example of waste is rarely significant, and where it is significant, it is typically easily eliminated by an expert. However, waste spread liberally across a code base can easily be significant and experts are not always as available as we would like. The aim of this rule (and the more specific rules that support it) is to eliminate most waste related to the use of C++ before it happens. After that, we can look at waste related to algorithms and requirements, but that is beyond the scope of these guidelines.

關于浪費的單獨的例子很少會造成顯著影響,即使造成顯著影響,通常也會很容易地被專家程式員排除。然而浪費會很容易地通過代碼傳播并顯著化,而且專家程式員也不是隻要我們需要就能有的。這個規則(和支援它的更具體的規則)的目的是在發生之前排除和C++用法相關的大部分浪費。

Enforcement(實施建議)

Many more specific rules aim at the overall goals of simplicity and elimination of gratuitous waste.

很多更具體的規則的總目标是簡單性和無謂浪費的排除。

  • Flag an unused return value from a user-defined non-defaulted postfix​

    ​operator++​

    ​​ or​

    ​operator--​

    ​ function. Prefer using the prefix form instead. (Note: "User-defined non-defaulted" is intended to reduce noise. Review this enforcement if it's still too noisy in practice.)

識别使用者定義的非預設字尾++操作符或者--操作符函數中的無用的傳回值。推薦使用prefix格式。(注意:“使用者定義的非預設”目的是為排除幹擾。如果在實踐中仍然存在太多幹擾,重新考慮本建議)

繼續閱讀