对象从堆栈中弹出

时间:2014-02-18 09:57:19

标签: c++ containers

示例代码:

class A
{
public:
    A(std::stack<A>* pStack){
        this->pStack = pStack;
    }

    void popMe(){
        pStack->pop();
    }
protected:
    std::stack<A>* pStack;
};

int main()
{
    std::stack<A> s;
    s.push(A(&s));
    s.top().popMe();
    return 0;
}

堆栈对象(或其他具有类似pop的方法的容器),每个对象都有指向堆栈的指针,因此它可以弹出自身(或其他类型容器的情况下的任何其他对象)。我的问题是:

  1. 从堆栈弹出时是否删除了对象?
  2. 调用popMe方法是安全的
  3. 是的,我知道这段代码很奇怪,难以理解/调试。任何更好的想法如何管理堆栈和堆栈(或包含此堆栈的对象)之间的对象之间的通信。

4 个答案:

答案 0 :(得分:2)

[1]堆栈中的对象总是被破坏!

[2]该方法不安全。如果对象不是当前的顶级对象怎么办?

[3]您可以扩展std :: stack适配器并通知要删除的对象:

#include <iostream>
#include <stack>

template <typename T>
class Stack
{
    private:
    typedef std::stack<T> stack_type;

    public:
    typedef typename stack_type::value_type value_type;
    typedef typename stack_type::reference reference;
    typedef typename stack_type::const_reference const_reference;
    typedef typename stack_type::size_type size_type;
    typedef typename stack_type::container_type container_type;

    public:
    explicit Stack(const container_type& container = container_type())
    : m_stack(container)
    {}

    bool empty() const { return m_stack.empty(); }
    size_type size() const { return m_stack.size(); }
    reference top() { return m_stack.top(); }
    const_reference top() const { return m_stack.top(); }
    void push(const value_type& x) { m_stack.push(x); }
    void push(value_type&& x) { m_stack.push(std::move(x)); }

    template<typename... Args>
    void emplace(_Args&&... args) {
        m_stack.emplace(std::forward<Args>(args)...);
    }

    void pop() {
        top().stack_pop_event(*this);
        m_stack.pop();
    }

    void swap(Stack& other) {
        m_stack.swap(other.m_stack);
    }

    private:
    stack_type m_stack;
};

class A
{
    public:
    void stack_pop_event(const::Stack<A>&){
        std::cout << "Pop\n";
    }
};

int main()
{
    Stack<A> s;
    s.push(A());
    s.pop();
    return 0;
}

(C ++ 11)

答案 1 :(得分:1)

1 - 将调用对象的析构函数。

2 - 你不检查指针是否为零。另外,想象下面的代码:

std::stack<A> s;
s.push(A(&s));
auto& head = s.top();
s.push(A(&s));
// ...
head.popMe(); //pops another element

3 - 请参阅boost :: intrusive容器。它有unlink hooks

答案 2 :(得分:0)

  1. 从堆栈弹出对象时是否删除了对象?
  2. 是。但它将是你推进的副本。

    1. 调用popMe方法是否安全
    2. 您可以在此处找到堆栈文档 http://www.cplusplus.com/reference/stack/stack/push/

      void push (const value_type& val);
      

      在堆栈顶部插入一个新元素,位于其当前顶部元素上方。此新元素的内容初始化为val。

      的副本

      所以std :: stack只存储副本。如果您希望它负责取消分配原始元素,您应该使用

      std::stack<std::shared_ptr<A>>
      

答案 3 :(得分:0)

  1. http://www.cplusplus.com/reference/stack/stack/pop/
  2. 没有针对nullptr的检查,所以一旦pStack指向null,你试图取消引用NULL ptr触发未定义的行为。