HOWTO · C++

C++ 中的 new 關鍵字和無匹配的操作符錯誤

一篇關於 C++ 中 new 關鍵字的使用以及使用中常見錯誤的解決方案的簡短文章。

本文將討論在 C++ 中使用 new 關鍵字。新手程式設計師在使用 new 關鍵字時通常會犯很多錯誤。

我們還將討論他們犯的一些最常見的錯誤及其潛在的修復方法。

C++ 中的 new 關鍵字

new 關鍵字用作向作業系統發出請求以在堆記憶體上分配一些空間的運算子。如果堆上可用的所需記憶體量,則分配它,並在指標變數中返回已分配和初始化記憶體的地址。

使用 new 關鍵字的語法是:

datatype pointer_variable_name = new datatype;

此資料型別也可以是一些隱式資料型別或任何類名。當我們使用 new 關鍵字建立類的指標變數時,將呼叫類建構函式,並在堆上分配記憶體。

如果我們不使用 new 關鍵字並且變數在堆疊上初始化,則該變數在超出範圍時會自動銷燬。但堆變數並非如此。

堆變數不會自動銷燬;相反,它們需要使用 delete 運算子手動銷燬;否則,它們會在記憶體中懸空,從而導致記憶體洩漏問題。

讓我們看看下面的例子。

#include <iostream>
using namespace std;

int main() {
  int *intPtr = new int;
  *intPtr = 10;
  cout << "Value of Integer pointer is: " << *intPtr << endl;
  delete intPtr;
  return 0;
}

輸出:

Value of Integer pointer is: 10

C++ 中 new 關鍵字的常見錯誤

在某些情況下,程式設計師沒有用正確的資料初始化它而使用未分配的資料,導致一些未知或不需要的資料會干擾程式執行。例如,有兩種情況:

int *ptr = new int;      // situation 1
int *ptr2 = new int[5];  // situation 2

在第一種情況下,記憶體分配給單個變數,而在第二種情況下,記憶體分配給 5 個整數變數,即在堆上建立一個包含 5 個索引的陣列。

假設我們通過使用第一種情況宣告指標來訪問 ptr[3]。在這種情況下,我們正在訪問一個未分配的空間,這可能會導致一些未知的錯誤,因為我們不知道之前在該記憶體位置放置了什麼。

因此,在分配和使用堆上分配的記憶體時,我們必須非常小心。

考慮一種情況,我們有一個類的指標,我們需要建立一個類物件陣列。

class Students {
  int roll_num;
  string name;
};
int main() {
  Students *student_list = new Students[10];
  for (int k = 0; k < 10; k++) {
    student_list[k] = new Students();  // line 10
  }
}

在上面的程式碼片段中,在第 10 行,我們在陣列的每個索引處初始化物件。但是這一行會產生這樣的錯誤:

/tmp/qqnmmMnApj.cpp: In function 'int main()':
/tmp/qqnmmMnApj.cpp:14:40: error: no match for 'operator=' (operand types are 'Students' and 'Students*')
   14 |         student_list[k] = new Students();
      |                                        ^

這是因為陣列 student_list 的每個索引都是 Students 類的物件,而不是 Students 類的指標。因此,我們不需要一個 new 關鍵字來初始化它。

它應該像這樣初始化:

student_list[k] = Students();

另一個常見錯誤是訪問已刪除或釋放的記憶體位置。在某些情況下,某些函式使用 delete 運算子從堆中釋放分配的記憶體,並且在程式中的任何其他點,你嘗試訪問該位置。

這可能會導致錯誤並且很難追蹤,尤其是在處理大型專案時。考慮下面的例子。

int main() {
  int *p = new int;
  *p = 5;
  cout << "before deletion: " << *p << endl;
  delete p;
  cout << "After deletion: " << *p << endl;
}

輸出:

before deletion: 5
After deletion: 0

我們可以在輸出中看到,刪除後,該值從記憶體中被擦除;因此,它返回零。在較大的專案中,這可能會在執行時導致不需要的錯誤,因為在某些情況下,釋放的記憶體位置可能被其他程式獲取,並且包含可能干擾程式邏輯的其他資料。