std :: stack&lt;的深层副本boost :: shared_ptr <t>&gt; </t>

时间:2010-11-03 13:17:45

标签: c++ boost stl stack containers

我想实现std::stack< boost::shared_ptr<T> >的副本。没有3份副本有没有办法做到这一点?这是代码:

template<typename T>
void copyStackContent(std::stack< boost::shared_ptr<T> > & dst,
                      std::stack< boost::shared_ptr<T> > const & src){

    //// Copy stack to temporary stack so we can unroll it
    std::stack< boost::shared_ptr<T> > tempStack(src);

    /// Copy stack to array
    std::vector< boost::shared_ptr<T> > tempArray;
    while(!tempStack.empty()){
        tempArray.push_back(tempStack.top());
        tempStack.pop();
    }

    /// Clear destination stack
    while(!dst.empty()){
        dst.pop();
    }

    /// Create destination stack
    for(std::vector< boost::shared_ptr<T> >::reverse_iterator it =
        tempArray.rbegin(); it != tempArray.rend(); ++it){
        dst.push( boost::shared_ptr<T>(new T(**it)) );
    }
}

样本测试:

void test(){
    // filling stack source
    std::stack< boost::shared_ptr<int> > intStack1;
    intStack1.push( boost::shared_ptr<int>(new int(0)) );
    intStack1.push( boost::shared_ptr<int>(new int(1)) );
    intStack1.push( boost::shared_ptr<int>(new int(2)) );
    intStack1.push( boost::shared_ptr<int>(new int(3)) );
    intStack1.push( boost::shared_ptr<int>(new int(4)) );

    // filling stack dest
    std::stack< boost::shared_ptr<int> > intStack2;
    copyStackContent(intStack2, intStack1);

    assert(intStack1.size() == intStack2.size());         // same size
    while(!intStack1.empty()){
        assert(intStack1.top() != intStack2.top());       // != pointers
        assert((*intStack1.top()) == (*intStack2.top())); // same content
        intStack1.pop();
        intStack2.pop();
    }
}

4 个答案:

答案 0 :(得分:2)

在这种情况下,您最好的选择可能只是使用deque而不是stack,并根据需要将top更改为back等。然后你可以一次迭代并进行深层复制。

交替找出您需要深层副本的原因并尝试从源头删除该需求。

答案 1 :(得分:2)

如果你想保持顺序,那么你就会陷入困境,因为堆栈不提供任何迭代器。如果您不想使用双端队列,您至少可以通过按值传递源堆栈来使代码更清晰(并且更高效under certain circumstances):

template<typename T>
void copyStackContent(std::stack< boost::shared_ptr<T> > & dst,
                      std::stack< boost::shared_ptr<T> > src){

    // Copy stack to array
    std::vector< boost::shared_ptr<T> > tempArray;
    while(!tempStack.empty()){
        tempArray.push_back(tempStack.top());
        tempStack.pop();
    }

    // Clear destination stack
    while(!dst.empty()){
        dst.pop();
    }

    // Create destination stack
    for(std::vector< boost::shared_ptr<T> >::reverse_iterator it =
        tempArray.rbegin(); it != tempArray.rend(); ++it){
        dst.push( boost::shared_ptr<T>(new T(**it)) );
    }
}

虽然,我怀疑复制shared_ptrs指向的值。如果你要复制一切,为什么甚至动态分配呢?

答案 2 :(得分:1)

不,你所拥有的就像你将获得的那样高效。但是,如果您发现自己这样做,则可能只需使用std::vectorstd::deque而不是堆栈。 std::stack只是这些容器之一的包装器(通常是std::deque)如果你使用这些容器中的任何一个,你可以通过使用反向迭代器有效地反转序列,如果你正在使用std::deque 1}},你甚至可以使用push_front有效地插入另一边。

附注:你也应该让copyStackContent返回一个新的堆栈而不是通过引用获取目标堆栈。它更具可读性,分配新堆栈并简单地解除分配旧堆栈比清除现有堆栈中的所有元素要便宜。

答案 3 :(得分:-1)

我的第一个答案是daft,没有读完整个问题,这里是一个克隆操作的干净实现,用于汇总上面讨论的想法,但只使用堆栈......

template <typename T, typename _CT = boost::shared_ptr<T>, typename _ST = std::stack<_CT> >
struct cloner
{
  inline _CT copy(_CT t)
  {
    return _CT(new T(*t));
  }

  _ST operator()(_ST src)
  {
    _ST temp;

    while(!src.empty())
    {
      temp.push(copy(src.top()));
      src.pop();
    }

    while(!temp.empty())
    {
      src.push(temp.top());
      temp.pop();
    }
    return src;
  }
};