大二上 資料結構與演算法筆記 20241024

陆舟LandBoat發表於2024-10-24

一.inline

在 C 和 C++ 程式語言中,inline 關鍵字是一種函式修飾符,用於建議編譯器在編譯時將函式的程式碼直接插入到每個函式呼叫的地方,而不是進行常規的函式呼叫。這樣做的目的是減少函式呼叫的開銷,尤其是在函式體較小且呼叫頻繁的情況下。

作用和優點:

  1. 減少函式呼叫開銷:透過將函式程式碼直接插入到呼叫點,避免了函式呼叫的額外開銷,如引數傳遞、棧幀的建立和銷燬等。
  2. 提高程式執行效率:對於小型函式,inline 可以提高程式的執行效率,因為編譯器可以最佳化掉函式呼叫的額外開銷。
  3. 編譯器最佳化:使用 inline 函式可以讓編譯器有更多的機會進行最佳化,因為它可以在編譯時看到函式的完整定義。

注意事項:

  1. 編譯器的自由裁量:儘管你可以使用inline來建議編譯器行內函數,但編譯器有權決定是否實際進行內聯。編譯器會根據函式的大小、複雜度以及呼叫頻率等因素來決定是否內聯。
  2. 程式碼膨脹:過度使用inline可能會導致程式碼膨脹,因為函式的程式碼會在每個呼叫點被複制,這可能會增加程式的總大小。
  3. 除錯:使用 inline 函式可能會使得除錯變得更加複雜,因為函式的程式碼在多個地方被複制,這可能會影響偵錯程式的斷點設定和錯誤定位。

使用示例:

inline int add(int a, int b) {
return a + b;
}

在這個例子中,add 函式被宣告為 inline 函式,編譯器會嘗試在每個呼叫 add 的地方直接插入其程式碼,而不是進行常規的函式呼叫。

結論:

inline 是一種有用的函式修飾符,可以在適當的場景下提高程式的執行效率。然而,它並不是銀彈,需要根據實際情況謹慎使用。在現代編譯器中,即使沒有顯式宣告 inline,編譯器也會自動進行內聯最佳化。

二.遞迴函式中用區域性變數

寫遞迴函式的時候,遞迴時儘量在函式內部定義一個區域性變數來用,不使用整體變數進行遞迴。
全域性變數在遞迴呼叫中被修改,可能導致在不同的遞迴層次中出現衝突。每次遞迴呼叫都應該使用區域性變數來避免這種情況。

三.register int的應用

register int 是 C 和 C++ 程式語言中的一個概念,用於建議編譯器將變數儲存在 CPU 的暫存器中,而不是記憶體中。暫存器是 CPU 內部的一小部分高速儲存區域,訪問速度遠遠快於主記憶體。因此,將頻繁訪問的變數儲存在暫存器中可以提高程式的執行效率。

組成部分:
register:這是一個儲存類說明符,用於建議編譯器將變數儲存在暫存器中。
int:這是一個資料型別,表示整數。
使用場景:
在早期的 C 和 C++ 程式中,程式設計師可能會使用 register int 來宣告那些在迴圈或頻繁操作中使用,且對效能有較高要求的變數。例如:

register int i;
for (i = 0; i < 1000; i++) {
// 迴圈體
}
注意事項:
編譯器的自由裁量:儘管程式設計師可以使用 register 來建議編譯器將變數儲存在暫存器中,但編譯器有權忽略這個建議,因為編譯器會根據實際情況決定如何最最佳化程式碼。

現代編譯器的最佳化:隨著編譯器技術的發展,現代編譯器已經非常智慧,能夠自動決定哪些變數應該儲存在暫存器中。因此,顯式使用 register 的需求已經大大降低。

C++17 棄用:在 C++17 標準中,register 已經被標記為棄用,這意味著在未來的 C++ 版本中,這個關鍵字可能會被完全移除。

現代硬體的影響:現代 CPU 擁有更多的暫存器,以及更復雜的快取系統,這使得編譯器的自動最佳化更加有效,減少了程式設計師手動最佳化的必要性。

總的來說,register int 是一個遺留自早期程式設計實踐的概念,它反映了程式設計師試圖透過手動最佳化來提高程式效能的努力。然而,在現代程式設計實踐中,這種最佳化方式已經不再常見,編譯器的自動最佳化通常更加有效。

register int即RI。
在 C++ 程式碼中,RI 是一個宏定義(macro),用於宣告一個 register int 型別的變數。register 是 C++ 中的一個關鍵字,用於建議編譯器將變數儲存在暫存器中而不是記憶體中。這樣做的目的是為了提高訪問變數的速度,因為暫存器的訪問速度通常比記憶體快得多。

然而,需要注意的是,在現代編譯器中,register 關鍵字的影響已經非常有限,因為編譯器通常能夠自動做出最最佳化的決策。此外,從 C++11 開始,register 關鍵字已經不再被推薦使用,並且在 C++17 中被標記為棄用。

在提供的程式碼中,RI 被定義為 register int,這通常用於宣告一個區域性變數,例如:

RI i; // 使用 RI 宏定義宣告一個 register int 型別的變數 i

這行程式碼的作用等同於直接宣告一個 register int 型別的變數 i。在某些情況下,使用 register 關鍵字可能會對編譯器的最佳化產生一定的影響,但這種影響通常很小,而且在現代程式設計實踐中,通常不再使用 register 關鍵字。

四.getline

getline 是 C++ 標準庫中的一個函式,用於從輸入流中讀取一行字串。這個函式可以處理空格和換行符,與 cin >> 不同的是,getline 會讀取幷包含字串中的空格,直到遇到換行符。

函式的基本用法如下:

getline(istream& is, string& str);
  • is 是輸入流的引用,可以是 cin、檔案流(如 ifstream)或任何其他輸入流物件。
  • str 是一個字串變數的引用,用於儲存從輸入流中讀取的行。

函式從輸入流中讀取字元,直到遇到換行符('\n')為止。換行符不會被儲存在字串中,但會在字串末尾新增一個空字元('\0')以形成一個正確的字串終止符。

示例用法:

  1. cin 讀取一行:
#include <iostream>
#include <string>

int main() {
    std::string line;
    std::cout << "請輸入一行文字:" << std::endl;
    std::getline(std::cin, line);
    std::cout << "你輸入的行是:" << line << std::endl;
    return 0;
}
  1. 從檔案流中讀取一行:
#include <iostream>
#include <fstream>
#include <string>

int main() {
    std::ifstream file("example.txt");
    std::string line;
    if (file.is_open()) {
        while (std::getline(file, line)) {
            std::cout << line << std::endl;
        }
        file.close();
    } else {
        std::cout << "無法開啟檔案" << std::endl;
    }
    return 0;
}

注意事項:

  • 如果輸入流已經處於錯誤狀態(如檔案未開啟),getline 將不會讀取任何內容,並返回 false。
  • getline 可以正確處理包含空格的行,這與 cin >> 形成對比,後者會在遇到空格時停止讀取。
  • 如果需要從 cin 讀取多個值,並且希望包括空格,可以使用 getline 讀取整行,然後使用 std::istringstream 來分割該行。

五.istringstream的用法

istringstream iss1(line); 這行程式碼在C++中建立了一個名為 iss1istringstream 物件。istringstream 是定義在 <sstream> 標頭檔案中的一個類,它是標準庫中的一個字串流(string stream)類,用於將字串作為流來處理。

這裡的 istringstream 被用來從字串中讀取資料,就像從一個檔案或標準輸入流中讀取資料一樣。你可以使用流提取運算子 >>istringstream 物件中提取資料,這與從 cin 或檔案流中提取資料的方式相同。

具體來說,istringstream iss1(line); 這行程式碼做了以下幾件事:

  1. 建立了一個 istringstream 型別的物件 iss1
  2. line 字串作為引數傳遞給 iss1 的建構函式,這樣 iss1 就包含了 line 字串的內容。
  3. 現在,iss1 可以像處理標準輸入流 cin 一樣被用來讀取資料。例如,你可以使用 iss1 >> num; 來從 iss1 中讀取整數到變數 num

這種方式常用於需要從單個字串中多次讀取多個資料值的場景。透過將字串轉換為流,你可以使用標準的輸入流運算子來逐個提取字串中的值。

相關文章