[英]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.