stl容器和指针的奇怪行为

时间:2011-05-24 22:37:53

标签: c++ stl

我不明白为什么以下不起作用:

queue<int*> q;

int counter = 1;
for (int i = 0; i < 3; i++) {
    int a[1] = {counter};
    q.push(a);
    counter++;
}

while (!q.empty()) {
    int *top = q.front();
    q.pop();

    cout << top[0] << endl;
}

应该打印出来:1 2 3,而是打印出3 3 3。这是因为每次运行循环后队列中的指针都是相同的。为什么会这样?

4 个答案:

答案 0 :(得分:8)

您正在存储指向局部变量的指针,并在它们指向的局部变量超出范围之后使用这些指针。

换句话说:您正在调用Undefined Behavior

结果:不应打印出“1 2 3”。它不需要做任何事情,并允许做任何它喜欢的事情。 “3 3 3”对我来说似乎很合理,因为它也可以崩溃。

答案 1 :(得分:4)

int a[1] = {counter};
q.push(a);

不正确。它调用未定义的behvaiour,因为花括号(for-loop块)之外不存在a。即使它是明确定义的,你的代码还有另一个问题,queue中的所有项都是相同的,因为a(相同的内存)在循环中重复使用。

解决方案是:

int *a = new int[1];
a[0] = counter;
q.push(a);

如果你这样做,那么你当然要自己解除记忆。


但我想知道queue中的每个项目是否只有一个int,那么为什么不使用以下内容:

queue<int> q;

for (int i = 0; i < 3; i++) 
{
  q.push(counter);
  counter++;
}

或者如果你真的想要数组,那么为什么不使用std::queue<std::vector<int> >

std::queue<std::vector<int> > q;

for (int i = 0; i < 3; i++) 
{
  std::vector<int> v;
  v.push_back(counter);
  q.push(v); //dont worry - a copy of the vector is being pushed!
  counter++;
}

通过这种方式,您不必处理原始指针。您不必自己分配或释放内存,我认为这是一种安全的方法!

答案 2 :(得分:3)

您有未定义的行为,因为您将a的声明超出了您将其推入队列的循环结束范围。

可能发生的事情是a的内存位置每次都被重用,但绝对没有保证。下次运行它时可能会得到不同的输出,或者你可能会崩溃,或者恶魔可能飞出你的鼻孔。

答案 3 :(得分:1)

如果您坚持使用指向整数的指针,则以下代码可以执行您想要的操作:

#include <queue>
#include <iostream>

int main()
{
  std::queue<int*> q;

  int counter = 1;
  for (int i = 0; i < 3; i++) {
    int* a = new int;
    *a = counter;
    q.push(a);
    counter++;
  }

  while (!q.empty()) {
    int *top = q.front();
    q.pop();

    std::cout << *top << std::endl;
    delete top;
  }

  return 0;
}