簡體   English   中英

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

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

我想實現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();
    }
}

在這種情況下你最好的選擇是可能只是使用deque代替的stack ,並更改topback的需要等。 然后,您可以在一次傳遞中迭代並執行深層復制。

或者,找出為什么需要深層復制並嘗試從源頭刪除該需求。

如果你想維護這個順序,你就會陷入困境,因為stack不提供任何迭代器。 如果您不想使用雙端隊列,則至少可以通過按值傳遞源堆棧來使代碼更清晰( 在某些情況下更有效):

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指向的值。 如果你要復制一切,為什么甚至動態分配呢?

不,你所擁有的就像你將獲得的那樣高效。 但是,如果你發現自己這樣做,你應該簡單地使用std::vectorstd::deque而不是堆棧。 std::stack只是這些容器之一的包裝器(通常是std::deque )如果你使用這些容器中的任何一個,你可以通過使用反向迭代器有效地反轉序列,如果你使用的是std::deque ,您甚至可以使用push_front高效地插入另一端。

旁注:您還應該讓copyStackContent返回一個新堆棧,而不是通過引用獲取目標堆棧。 它更具可讀性,分配新堆棧並簡單地解除分配舊堆棧比清除現有堆棧中的所有元素要便宜得多。

我的第一個答案是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