我对堆栈顶部元素的引用感到困惑。
#include <iostream>
#include <stack>
using namespace std;
int main()
{
stack<int> s;
s.push(1);
int x = s.top();
int& y = s.top();
const int& z = s.top();
cout << x << '\t' << y << '\t' << z << endl;
s.pop();
s.push(2);
cout << x << '\t' << y << '\t' << z << endl;
}
/* Output:
1 1 1
1 2 2
*/我认为不应该更改对top元素的引用,但是在将一个新元素推入堆栈之后,引用所引用的值将被更改。
这对我来说很奇怪,因为如果堆栈的类型不是int,假设它是MyClass类型(非常大的数据),那么有什么方法可以安全地引用旧的top元素吗?(因为我不想做昂贵的复制操作)。
我想这种行为可能是依赖于实现的,签名!
发布于 2013-08-12 05:58:40
如C++11标准所述(23.6.5.2 - stack定义)
reference top() { return c.back(); }
const_reference top() const { return c.back(); }
...
void push(const value_type& x) { c.push_back(x); }
void push(value_type&& x) { c.push_back(std::move(x)); }
...
void pop() { c.pop_back(); }在使用默认的底层容器std::deque时,iterator/reference invalidation rules声明(引用this答案):
deque:擦除最后一个元素只使迭代器无效和对擦除元素和过去结束迭代器的引用无效;擦除第一个元素只使迭代器无效和对擦除元素的引用无效;擦除任何其他元素使所有迭代器和引用(包括过去-结束迭代器)都无效。
通过使用std::stack::pop,您必须调用std::deque::pop_back(),如前所述,使以前返回的引用无效(后者随后调用std::deque::back())。因此,您不应该依赖这种行为,因为它是未定义的,不可移植的,而且是错误的。
如果您想拥有堆栈顶部的原始值,那么解决方案就是复制top元素,而不是引用它。也就是说,如果您想在从堆栈中弹出一个元素之后正确地保留原始值。
发布于 2013-08-12 05:41:53
在pop()之后,引用无效。输出显示了由于std::堆栈的实现细节而产生的新推送值--不要依赖它,它也可能是垃圾。
https://stackoverflow.com/questions/18180127
复制相似问题