我只是無法理解指標 - 我應該何時以及如何準確地使用指標。無論我閱讀了多少視頻和文獻,我只是不明白我應該何時以及如何使用它。明明我就是那么濃...
讓我們在這里看看這個例子:
int main()
{
int* ptr = new int(10);
std::cout << ptr << std::endl;
std::cout << *ptr << std::endl;
std::cout << &ptr << std::endl;
}
這將回傳給我們一個像這樣的值:
000001A68ABB5250
10
000000455ADCF828
這些輸出是什么意思?第一個和第三個看起來像是記憶體中的地址號,但它們不同,我不明白它們應該做什么?第二個是我分配的值,但為什么我必須用指標符號來獲取它?
讓我們看看這個:
int main()
{
int ptr = 10;
std::cout << ptr << std::endl;
//std::cout << *ptr << std::endl; //gives "Error(active) E0075 operand of '*' must be a pointer but has type 'int'"
std::cout << &ptr << std::endl;
}
分別回傳:
10
000000D9242FF5F4
是什么使上面的代碼與此示例代碼不同?為什么我不必使用指標來獲取值?與號顯示記憶體地址對嗎?
基本上有人可以用最愚蠢、最容易理解的方式向我解釋指標的意義是什么以及為什么我們在 C 中需要它們。
uj5u.com熱心網友回復:
如果我們“繪制”第一個示例,它將是這樣的:
------ ----- -------------- | &ptr | --> | 指標 | --> | *ptr int(10) | ------ ----- --------------
ptr指向一個int值(初始化 10 )也是如此10。并且&ptr指向變數ptr。
在第二個示例中,變數名稱ptr具有誤導性,因為它不是指標。這是一個簡單的int變數。
畫出來會像
------ ------------- | &ptr | --> | 指標 int(10) | ------ -------------
uj5u.com熱心網友回復:
當我第一次開始編程時,指標是我剛剛接受它們作業并最終積累了足夠的經驗來學習/理解它們的東西之一。
在我的一堂課上,一位教授說當你想修改一個物件而不是復制它時,最好使用指標。將值傳遞給函式會創建在其中傳遞的物件的副本。
uj5u.com熱心網友回復:
首先要理解的是,符號的含義*取決于&背景關系。
在int* ptr,*表示“這是一個指標”。
但除此之外(例如 in cout << *ptr),*意味著“取消參考”一個指標。即,給定一個指向 X 的指標,*回傳 X,無論發生什么。
&(例如 in cout << &ptr)“獲取地址”的東西。給定 X,它給你一個指向 X 的指標。
&和*(在第二種意義上)是相反的操作,它們相互抵消。
int* ptr = new int(10);有點類似于,int x = 10; int *ptr = &x;這反過來意味著int x = 10; int *ptr; ptr = &x;(不是*ptr = &x,因為*在這里意味著不同的東西,見上文)。
所以,給定int x = 10;,&x是一個“指向 x 的指標”(列印它會給你一個地址)。完成后int *ptr = &x,ptr也是一個“指向 x 的指標”,因此列印它會顯示相同的地址。
*ptr給你x,就像*&x(這意味著*(&x))一樣,因為*和&相互抵消。
指標可以指向其他指標。&ptr給你一個“指向”的指標ptr,或“指向 x 的指標”,它的型別為int **. **&ptr因此將回傳 的值x。
uj5u.com熱心網友回復:
我不是一個解釋者,但總體概述是:
在你宣告和定義之后int* ptr = new int(10);
當你使用 ptr 時,它是型別的名稱int*,比如 for int x = 5,當你使用 x 時,它是 int 型別的。
ptr是一個指標,所以它是一個存盤在地址中的變數,所以當你列印它時,它將是一個地址。
&ptr將是指標的地址,是的,指標也有地址。基本上,它是 type int**,所以列印時也會是一個地址。
*ptr取消參考指標,因此它將獲得存盤在指標指向的記憶體位置中的值 10。可以把它想象成,每個地址都指向一個存盤值的記憶體位置。
如果它只是 plain int ptr = 10,則不能取消參考它: apply*ptr因為它是 typeint而不是int*.
但是,如果您&ptr向它申請,它將獲得int ptr本質上是 type的地址int*。
例如,如果你這樣做:int x = 5; int *ptr = &x;,如果你取消參考ptr,并做:cout << *ptr,它將列印 5。
我第一次也很難用指標。沒關系。我花了一個月左右的時間來解決這個問題。事實上,我仍然有一些讓我感到困惑的事情。哦,好吧,我不太擅長解釋,可能和你讀到的差不多……祝你好運。
uj5u.com熱心網友回復:
簡而言之:
int* ptr = new int(10);
ptr (int)實際上只是您在右側分配的 int 的記憶體地址(一個數字)。
std::cout << ptr << std::endl;
然后列印出新 int 的記憶體地址。這是因為 ptr只是一個恰好是記憶體地址的數字。
std::cout << *ptr << std::endl;
在這里,您告訴 C 使用 ptr 所在的數字訪問記憶體地址。因為 ptr 是 int 的記憶體地址,所以你會得到 int 的值。
std::cout << &ptr << std::endl;
最后,你告訴 C 給你 ptr 的記憶體地址。如果您使用 *&ptr,那么您將得到與您的第一個列印陳述句相同的結果。
至于后半部分,這里的 int 只是一個值,而不是指標。當 C 說你不能使用 * 時,它可以防止你不小心把 int 當作記憶體地址。但是,如果您真的想將 int 視為記憶體地址,
int* x = 10
然后將允許*x編譯。現在因為這是訪問記憶體地址 10 的 int (這不是您的程式的一部分),您的作業系統幾乎肯定會殺死您的程式。
uj5u.com熱心網友回復:
真正有趣的問題是“為什么要使用指標?” 如果你明白了,那么其余的可能會隨之而來。
旁注,C 有許多結構,這些結構使很多“隱藏”,但我所描述的仍在幕后進行
有幾種情況下指標很有用
#1 傳遞大事
想象一下你有這個
struct Biggy{
int Widle[500];
char Froodle[500];
}
這是一個大物件,復制起來很費錢,你有一個對 Biggy 物件進行操作的函式,比如說它比較 Widle 和 Froodle 陣列。
bool AreTheSame(Biggy b) {....}
c 和 c 的作業方式是引數按值傳遞,這意味著它們從呼叫者復制到被呼叫函式
所以當我這樣做的時候
Biggy b = MakeAndFillBiggy(); // we will come back to this function
bool same = AReTheSame(b);
所有 1000 個位元組都被復制,這很昂貴
但如果我有
bool AreTheSame(Biggy *b) {....}
那我可以
bool same = AretheTheSame(&b);
現在我只是傳遞一個指標。那是 4 或 8 個位元組而不是 1000。
#2 允許函式修改其引數
正如所指出的
bool same = AreTheSame(b);
將 b 的副本傳遞給函式,這很昂貴,但如果函式想要更改 b 它也不能。它只有一個副本。
想象一下,我們有一個函式MakeTheSame(Biggy b);來查看兩個陣列是否相同,如果不是,它會改變它們,很好。但是像這樣它沒有用,因為它改變了副本,而不是原件。
我們又可以做
void MakeTheSame(Biggy *b) {..}
...
Biggy b = MakeAndFillBiggy(); // we will come back to this function
bool same = MakeTheSame(&b);
now we are passing a pointer to the callers 'b'
Note that this is useful for any size object.
You have probably seen this
int num;
scanf("%d", &num);
we have to pass the pointer to num so that scanf can modify it.
#3 To get and use dynamic memory
YOu have an app that keeps a list of football teams for a tournament.
struct Team{
string name;
string town;
string captain;
}
How big does the array that holds it need to be? YOu dont know in advance how many teams will enter.
YOu could have
Team teams[100];
But thats a bit wasteful. So instead you use dynamic memory, every time you get a new time you allocate a new Team object on the heap.
Team *team = new Team();
'new' allocates memory dynamically from a pool , it will be big enough for a Team object and it will be initialized. It returns a pointer to this new memory.
Now you can have just the right amount of Team objects.
Lets go back to this
Biggy b = MakeAndFillBiggy(); // we will come back to this function
Now we will do
Biggy *MakeAndFillBiggy(){
Biggy * b = new Biggy();
... fill arrays somehow
return b;
}
and now we do
Biggy *b = MakeAndFillBiggy();
C goodies
C has a thing called references. These behave like pointers (cheap to pass, allow functions to change their arguments) but syntactically look like non pointers.
Eg
void MakeTheSame(Biggy &b) {..}
this says that MakeTheSame takes a referenc as an argument. Now we can do
Biggy b;
MakeTheSame(b);
There are some advantages to references over pointers but they do exactly the same thing
C has 'smart pointers'
The problem with our function
Biggy *MakeAndFillBiggy(){
Biggy * b = new Biggy();
... fill arrays somehow
return b;
}
Biggy *b = MakeAndFillBiggy();
Is that it retunr a pointer to an object on the heap. When we have finished with it we have to realease its memory back to the pool so it can be reused.
so somewhere there has to be
delete b;
The problem is that in complex code it might be hard to knwo when you have finished with b. Enter 'smart pointers' they detect when you have finished with the memory and release it for you
so you will see
std::shared_ptr<Biggy> MakeAndFillBiggy(){
std::shared_ptr<Biggy> p = std::make_shared<Biggy>();
... fill arrays somehow
return b;
}
std::shared_ptr<Biggy> b = MakeAndFillBiggy();
or more succintly becuase the compiler is smart
std::shared_ptr<Biggy> MakeAndFillBiggy(){
auto p = std::make_shared<Biggy>();
... fill arrays somehow
return b;
}
auto b = MakeAndFillBiggy();
under the hood exactly the same thing is happening, theres just some glue added on top to keep track of when this pointer is not longer needed
Inside there was still ptr = new xxx and a *p
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/434179.html
上一篇:c中的qsort型別轉換指標
