2010-11-03 65 views
1

我想實現一個std::stack< boost::shared_ptr<T> >的副本。有沒有辦法做到沒有3份?下面是代碼:std :: stack的深拷貝<boost :: shared_ptr <T>>

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

回答

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。爲什麼即使動態分配,如果你要無論如何要複製一切?

+1

目標堆棧可能應該按值返回,而不是使用目標。 +1。 – 2010-11-03 13:43:10

+0

那麼,我的T需要在分配時進行對齊,所以它不是真的使用新的,而是一個特定的分配器。 – tibur 2010-11-03 13:56:00

+0

第一次複製之前不應該有tempArray.reserve(src.size())嗎?或者這會不成熟的優化? – Basilevs 2010-11-03 14:23:26

1

沒有,你有什麼是關於有效率,你會得到。但是,如果您發現自己正在執行此操作,則應該簡單地使用std::vectorstd::deque而不是堆棧。 std::stack僅僅是這些容器中的一個容器的包裝(通常爲std::deque)如果使用這兩個容器中的任何一個,則可以通過使用反向迭代器有效地反轉序列,並且如果使用的是std::deque,則甚至可以在另一側插入有效使用push_front

附註:您也應該可能有copyStackContent返回一個新的堆棧,而不是引用目標堆棧。它更具可讀性,分配一個新堆棧並簡單地釋放舊堆棧比清除現有堆棧中的所有元素要便宜。

-1

我的第一個答案是愚蠢的,沒有閱讀的整個問題,這裏是一個乾淨的執行堆棧彙集上面討論的想法,但只有使用棧克隆操作的......

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; 
    } 
}; 
+0

這並不複製堆棧的內容,只複製堆棧本身。 – 2010-11-03 13:31:35

2

在這種情況下,您最好的選擇是根據需要使用deque而不是stack並將top更改爲back等。然後,您可以迭代並一次完成深層複製。

或者找出爲什麼你需要深層複製,並試圖從源頭消除該需求。

+0

+1,因爲我忘記提到要首先避免深層複製。 – 2010-11-03 13:36:38

相關問題