简体   繁体   English

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

[英]Deep copy of std::stack< boost::shared_ptr<T> >

I would like to implement a copy of std::stack< boost::shared_ptr<T> > . 我想实现std::stack< boost::shared_ptr<T> >的副本。 Is there any way to do it without 3 copies? 没有3份副本有没有办法做到这一点? Here is the code: 这是代码:

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)) );
    }
}

And a sample test: 并进行了样本测试:

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();
    }
}

In this case your best bet is to probably just use a deque instead of a stack and change top to back etc as needed. 在这种情况下你最好的选择是可能只是使用deque代替的stack ,并更改topback的需要等。 Then you can iterate and do the deep copy in one pass. 然后,您可以在一次传递中迭代并执行深层复制。

Alternately figure out why you need the deep copy and try to remove that need at its source. 或者,找出为什么需要深层复制并尝试从源头删除该需求。

If you want to maintain the ordering, you're kind of stuck since stack doesn't provide any iterators. 如果你想维护这个顺序,你就会陷入困境,因为stack不提供任何迭代器。 If you don't want to use a deque, you can at least make the code clearer (and more efficient under certain circumstances ) by passing the source stack by value: 如果您不想使用双端队列,则至少可以通过按值传递源堆栈来使代码更清晰( 在某些情况下更有效):

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)) );
    }
}

Though, I am suspicious of copying the values pointed to by shared_ptrs. 虽然,我怀疑复制shared_ptrs指向的值。 Why even dynamically allocate if you're going to be copying everything anyhow? 如果你要复制一切,为什么甚至动态分配呢?

No, what you have is about as efficient as you're going to get. 不,你所拥有的就像你将获得的那样高效。 However, if you find yourself doing this, you should probably simply use a std::vector or std::deque instead of a stack. 但是,如果你发现自己这样做,你应该简单地使用std::vectorstd::deque而不是堆栈。 std::stack is merely a wrapper around one of these containers (usually std::deque ) If you use either of these containers, you can effectively reverse the sequence by using reverse iterators, and if you're using a std::deque , you can even insert on the other side efficiently using push_front . std::stack只是这些容器之一的包装器(通常是std::deque )如果你使用这些容器中的任何一个,你可以通过使用反向迭代器有效地反转序列,如果你使用的是std::deque ,您甚至可以使用push_front高效地插入另一端。

Side note: You should also probably have copyStackContent return a new stack instead of taking a destination stack by reference. 旁注:您还应该让copyStackContent返回一个新堆栈,而不是通过引用获取目标堆栈。 It's more readable, and it can be cheaper to allocate a new stack and simply deallocate the old one than to erase all the elements from the existing stack. 它更具可读性,分配新堆栈并简单地解除分配旧堆栈比清除现有堆栈中的所有元素要便宜得多。

My first answer was daft, didn't read the whole question, here is a clean implementation of a clone operation for stack bringing together the ideas discussed above, but using stacks only... 我的第一个答案是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;
  }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM