讓我們一行看看代碼行:只
struct Node {
int val;
Node* left;
Node* right;
Node* parent;
Node(int value, Node* left, Node* right, Node* parent): val(value), left(left), right(right), parent(parent){}
};
void main() {
Node *root, *temp, *temp_before;
root = new Node(0, NULL, NULL, NULL); // root points to the newly allocated memory
temp_before = root; //temp_before also points to that memory
temp = temp_before->left; // temp points to the left of root, which is null
// NOTE: at this point, temp isn't connected to the tree, even if you allocate memory with it.
// You only have pointers ("handles") for those memory blocks but you haven't combined them together yet.
temp = new Node(5, NULL, NULL, NULL); // This allocated memory for the memory address pointed by temp
// temp = root->left; //error
root->left = temp; //correct one
// Now root->left points to the memory block you allocated with temp
}
當使用指針分配內存時,指針指向的內存塊。除非手動將它們連接在一起,否則它們不會成爲連接結構。
這就是你想要做的,但以錯誤的方式。可以這樣想:當你分配內存時,操作系統給你一個主內存的空間。它通過給你一個「引用」到這個內存塊來完成它,這樣你就可以使用那個內存塊。這就是爲什麼指針也被稱爲「句柄」的原因,因爲它們是您與內存塊交互的方式。
在錯誤的行中,您重寫了剛分配的內存的句柄。當你這樣做時,你會失去對該內存塊的訪問權限,直到程序執行結束。這些重寫被稱爲「內存泄漏」,因爲這塊內存是你問的但忘記的東西。
當您執行temp = root->left;
,它會覆蓋另一個指針的指針(在這種情況下,一個指向NULL
),當您嘗試打印,它給你一個錯誤稱爲null pointer exception
,從名字上就可以清楚地看到問題:)
當你過度複雜的事情,你正在嘗試做,這些錯誤發生 往往會發生,尤其是如果你對內存不熟悉。您可以簡化這種代碼的方法是:
void main() {
Node* root = new Node(0, NULL, NULL, NULL); // Allocate root
root->left = new Node(5, NULL, NULL, NULL); // This line means "add a new node to the left of my root"
std::cout << root->val << std::endl;
std::cout << root->left->val << std::endl;
}
如果上面的實施鬥爭,認爲它是這樣的:
Node* temp = new Node(5, NULL, NULL, NULL);
root->left = temp;
此代碼是相同main
函數的代碼。可以這樣想:您正在分配一個內存塊並使用句柄temp
訪問它。之後,你分配處理的信息到您的根的左節點指針。這樣,即使您無法再訪問temp
,也可以通過root->left
訪問相同的內存塊。
下面的代碼是你怎麼想的。嘗試思考這兩者之間的差異,一旦你找出它,指針將更有意義:
Node* temp = root->left;
temp = new Node(5, NULL, NULL, NULL);
你在哪裏設置樹中的一個節點指向'temp'? – NathanOliver
未初始化的本地非靜態變量(如您所擁有的變量)在初始化它們之前具有* indeterminate *值。使用這些未初始化的變量會導致*未定義的行爲*。 –
指向您將root-> left設置爲除null之外任何其他行的行 – pm100