[英]Trying to understand pointers in C++
我正在嘗試使用Jesse Liberty的“ 24小時內自學C ++”自己學習C ++。 我寫了這個簡短的程序來找出C ++中的指針。
#include <iostream>
void hMany(int count); // hMany function prototype
void hMany(int count){
do {
std::cout << "Hello...\n";
count--;
} while (count >0 );
};
int main (int argc, const char * argv[]) {
int counter;
int * pCounter = &counter;
std::cout << "How many hellos? ";
std::cin >> counter;
hMany(*pCounter);
std::cout << "counter is: " << counter << std::endl;
std::cout << "*pCounter is: " << *pCounter << std::endl;
return 0;
}
結果輸出為:
How many hellos? 2
Hello...
Hello...
counter is: 2
*pCounter is: 2
傳遞指針(* pCounter)與傳遞參數(counter)有什么好處?
任何幫助將不勝感激。 路易斯
更新:
好。 該程序正在運行,我現在完全了解C ++指針。 謝謝大家的答復。 嘗試了Chowlett的代碼后,我得到了2條警告(不是錯誤)。 一個是! 沒有函數hMany和* pCount--的原型! 表達式結果未使用。 我能夠自行糾正原型,但無法弄清楚* pCount--警告。
我向我的朋友托尼求助,這是他的答案。
括號使事情按正確的順序發生。
(*pCount)--
表示跟隨指針指向它所指向的整數,然后遞減該整數,這就是您要執行的操作。
*pCount--
最終做錯了事,編譯器將其視為
*(pCount—)
它說要先遞減指針,然后將其指向要更改的指針之前的“整數”(沒有這樣的事情,因為只有一個整數調用了此函數),然后跟隨此遞減的指針而不執行任何操作在該內存位置帶有整數。 這就是為什么編譯器抱怨表達式結果未使用的原因。 編譯器是正確的。 此代碼會錯誤地遞減指針,獲取錯誤的整數,並且不會在任何地方存儲該錯誤的整數。
對於那些對C ++陌生的人來說,這是正確的代碼。
無效hMany(int * pCount); // hMany函數原型
void hMany(int * pCount){// * pCount接收計數地址
do {
std::cout << "Hello...\n";
// The parentheses make things happen in the correct order.
// says to follow the pointer to the integer it points to,
// and then decrement the integer.
(*pCount)--;
} while (*pCount >0 );
}
int main(int argc,const char * argv []){
int counter;
int * pCounter = &counter;
std::cout << "How many hellos? ";
std::cin >> counter;
hMany(pCounter); // passing the address of counter
std::cout << "counter is: " << counter << std::endl;
std::cout << "*pCounter is: " << *pCounter << std::endl;
return 0;
}
int counter;
int * pCounter = &counter;
...
hMany(*pCounter); // Pass by value
hMany(counter); // Pass by value
傳遞點(* pCounter)與傳遞參數(counter)有什么好處?
在這種情況下,什么都沒有,僅是一個教育示例。 它顯示您可以取消引用指針並通過*
獲得其值。
此外,這兩種情況都是按價值傳遞的。
在實踐中,除非有充分的理由,否則應避免默認使用指針。
使用*pCounter
和counter
沒有什么區別。 在這兩種情況下,您都將傳遞變量counter
的值 。 但是,如果您實際上傳遞了指針本身,則會得到不同的行為。
考慮稍微不同的程序:
#include <iostream>
void hMany(int* pCount); // hMany function prototype
void hMany(int* pCount){
do {
std::cout << "Hello...\n";
--*pCount;
} while (*pCount >0 );
}
int main (int argc, const char * argv[]) {
int counter;
int * pCounter = &counter;
std::cout << "How many hellos? ";
std::cin >> counter;
hMany(pCounter);
std::cout << "counter is: " << counter << std::endl;
std::cout << "*pCounter is: " << *pCounter << std::endl;
return 0;
}
在這種情況下,您的輸出將是:
How many hellos? 2
Hello...
Hello...
counter is: 0
*pCounter is: 0
通過將指針傳遞到counter
(字面上是counter
內存中的地址),您可以允許函數通過其存儲位置來更改counter
。
傳遞點(* pCounter)與傳遞參數(counter)有什么好處?
沒有“好處” ,這就是您應該傳遞指針pCounter
指向的值的方式。
hMany(*pCounter)
->取消引用pCounter
以獲取值
不同之處在於變量的范圍。
如果傳遞變量,它將在函數的本地范圍內復制到堆棧中。 更改該值的操作將在本地復制中完成,如果是這種情況,則第一,如果傳遞了大變量,則使用空間;第二,您需要從函數中返回該值(因為一旦執行該操作,堆棧將被破壞背部)
您可以這樣想:
堆:
當前函數堆棧:
[ ]
[ ]
[ ]
[ ]
當您調用另一個1元素時
[ ]
[ ]
[ ]
[ ]
[newel]
當您離開該功能時,它將被刪除,因此再次像這樣
[ ]
[ ]
[ ]
[ ]
新元素的價值不再受信任。
但是,如果這是指針的副本,則不要更改指針副本的值,而是要更改指針所指向的位置的值,因此堆棧將像這樣
[ ]
[ actual_value]
[ ]
[ pointer_to_value]
比您調用該函數
[ ]
[ actual_value]
[ ]
[ pointer_to_value]
[ pointer_to_value_copy]
這將更改堆棧上的actual_value,並退出刪除pointer_to_value的副本
[ ]
[ actual_value**changed]
[ ]
[ pointer_to_value]
指針實際上包含具有該內存地址表示的值的類型信息的內存地址。 它可以用於在內存地址中傳遞實體,而無需再次實例化它來更改其值或類似的值。
但是在您的程序中,使用指針不會帶來任何好處,因為在您的情況下,一個c ++函數hMany
在內部重新實例化了其參數中的值類型,在您的情況下為'int count'。
正如其他答案指出的那樣,您需要將count指針傳遞給該函數。 在那種情況下,C ++函數將在其參數中重新實例化值的類型,但是由於類型是指針,因此程序將在C ++函數內部具有正確的count
內存地址,並且可以正確更改正確標識的值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.