[英]Did not understand C++ stack<char*> behavior
我被困了兩個小時,試圖了解這個簡單的 C++ 測試程序中發生了什么,但仍然沒有得到它。 它應該只接收三個字符串作為輸入,將它們插入堆棧,最后打印同一堆棧的所有元素。
#include <iostream>
#include <stack>
#include <cstring>
using namespace std;
int main(){
stack<char*> stk;
int stringLength;
for (int i=0; i<3; i++){
char new_element[200];
scanf("%s", new_element);
stringLength = strlen(new_element);
stk.push(new_element);
}
cout << "Stack content: ";
while(!stk.empty()){
cout << stk.top() << " ";
stk.pop();
}
cout << endl;
}
奇怪的是,最終的 output 是相同的元素(最后添加的)打印了 3 次,這對我來說毫無意義。
例如,如果輸入是:
John
Mary
Rick
那么當前的 output 是
Rick
Rick
Rick
誰能幫我理解和解決這個問題?
char new_element[200];
// [...]
stk.push(new_element);
您在堆棧 object 中推送相同的指針。
更糟糕的是,您正在推送系統堆棧指針,因此如果您要從 function 外部使用堆棧,您會遇到訪問沖突(Linux 中的段錯誤)並崩潰。 在您的情況下,您並沒有從外部使用它們,因為堆棧 object 也在堆棧上。
無論如何,有兩個快速修復:
編寫正確的代碼:使用string
並讓編譯器找出復制它們並根據需要清理它們。
不要編寫正確的代碼:使用strdup
獲取唯一的字符串指針。 您可能希望或不希望在某個時候釋放它們,對於選擇這條路線的人來說,這似乎總是可選的。
因為您已將stk
聲明為std::stack<char*>
,所以它的元素將是char*
,或指向char
數據的指針(即地址)。
那么,執行stk.push(new_element);
時你會做什么行是將您的(本地)字符數組的地址放入堆棧中。 從技術上講,當您稍后pop
該地址並打印它指向的字符串時,您正在執行未定義的行為,因為指向的 memory 已超出 scope (它的“生命周期”只是第一個for
循環的一次迭代)。
但是,您的系統只是在每次循環迭代中重復使用相同的地址/緩沖區,因此您的scanf("%s", new_element);
行每次都替換該緩沖區的內容。 然后,當您打印三個堆棧元素的內容時,每一個都將是相同的地址,您只是顯示該緩沖區的最后修改版本。
要解決此問題,請為您的“本地”變量使用std::string
(然后將通過push
調用復制該變量); 或者,如果您堅持使用char*
,則推送使用strdup()
function 創建的副本的地址:
for (int i=0; i<3; i++){
char new_element[200];
scanf("%s", new_element);
stringLength = strlen(new_element);
stk.push(strdup(new_element)); // Allocate and copy the buffer before pushing
}
然后,在第二個循環中,完成后不要忘記釋放 memory:
while(!stk.empty()){
cout << stk.top() << " ";
free(stk.top()); // Release the allocated memory before we lose the pointer
stk.pop();
}
strdup()
和free()
函數在<stdlib.h>
header 文件中聲明。
您可以使用string
而不是char*
#include <iostream>
#include <stack>
#include <cstring>
int main(){
stack<string> stk;
int stringLength;
for (int i=0; i<3; i++){
string new_element;
cin>>new_element;
cout<<new_element<<"\n";
stk.push(new_element);
}
cout << "Stack content: ";
while(!stk.empty()){
cout << stk.top() << " ";
stk.pop();
}
cout << endl;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.