将元素从 std::vector 复制到 std::stack c++

Posted

技术标签:

【中文标题】将元素从 std::vector 复制到 std::stack c++【英文标题】:Copy elements from std::vector into std::stack c++ 【发布时间】:2016-03-30 21:20:36 【问题描述】:

我需要将std::vector 复制到std::stack

    是不是遍历vector,压栈才是唯一的办法?

    如果有其他方法,从性能的角度来看,什么是更好的选择?

代码:

 std::stack<A>   m_stack;
 std::vector<A>  m_vec;

 for (auto& elem : m_vec)
 
    m_stack.push(elem);
 

【问题讨论】:

【参考方案1】:

由于堆栈是容器适配器,您可以从底层容器创建堆栈:

std::vector<A> m_vec = /* ... */;
std::stack<A, std::vector<A>> m_stack(m_vec);

或者,如果您希望您的堆栈支持deque-backed:

std::stack<A> m_stack(std::deque<A>(m_vec.begin(), m_vec.end()));

【讨论】:

这里会发生复制吗? @HumamHelfawi:是的。我认为 OP 想要那个,因为她说“我需要复制”。如果不再需要原件,也可以将矢量移入。 @KerrekSB 谢谢,我只是要求不要批评 :) 我在评论之前投了赞成票;) @basav 为什么不呢? std::containers 与 std 库中的几乎所有其他内容一样具有移动感知能力 @TM:除了使用循环,或者可能派生自己的适配器并添加这样的工具之外,您无法做到这一点。检查the documentation 的(非常短的)界面以了解您可以做什么和不能做什么。如果账单不合适,不要费心使用堆栈,只需使用向量并堆栈一样操作它。不惜一切代价使用std::stack 是没有奖品的。【参考方案2】:

一些有趣的堆栈展示了从另一个容器获取值到堆栈的各种方法。

假设我们提供了适当的定义:

template<class T, class Container>
auto stack_pusher(std::stack<T, Container>& stack);

我们可以这样写:

int main()

    using namespace std;

    // construct an initial vector
    vector<int> init  7,6 ;

    // construct a stack using a copy of the initial vector's elements
    // note that the stack's storage is automatically deduced
    stack<int> stack1   begin(init), end(init)  ;

    // construct a stack directly from a container initialised with an initialiser list
    stack<int> stack2   3,4,5  ;

    // another vector
    vector<int> myvector  1, 2, 3, 4, 5, 6, 7, 8 ;

    // copy vector onto stack using a forward iterator
    copy(begin(myvector),
         end(myvector),
         stack_pusher(stack1));

    // copy vector onto stack using a reverse iterator
    copy(rbegin(myvector),
         rend(myvector),
         stack_pusher(stack2));

    // display the stacks
    while (stack1.size() or stack2.size())
    
        // function to encode an optional T as a string
        auto encode = [](const auto& opt)
        
            return opt ? std::to_string(opt.value()) : std::string("*");
        ;

        // function to pop a value from a stack if it's not empty.
        // return an optional
        auto maybe_pop = [](auto& stack)
        
            using element_type = std::decay_t<decltype(stack.top())>;
            boost::optional<element_type> result;
            if (stack.size()) 
                result = stack.top();
                stack.pop();
            
            return result;
        ;

        cout
        << encode(maybe_pop(stack1))
        << "\t"
        << encode(maybe_pop(stack2)) << endl;
    

    return 0;

输出将是:

8       1
7       2
6       3
5       4
4       5
3       6
2       7
1       8
6       5
7       4
*       3

这是完整的清单 (c++14):

#include <iostream>
#include <stack>
#include <vector>
#include <deque>
#include <iterator>
#include <utility>
#include <boost/optional.hpp>

// an iterator that pushes values onto a stack
template<class Stack>
struct push_iterator
: std::iterator<std::output_iterator_tag,void,void,void,void>

    push_iterator(Stack& stack)
    : pstack(std::addressof(stack))
    

    template<class T>
    auto& operator=(T&& t)
    
        pstack->push(std::forward<T>(t));
        return *this;
    

    auto& operator*() 
        return *this;
    

    auto& operator++() 
        return *this;
    

private:
    Stack* pstack;
;

// convenience class to make a push_iterator of the correct type
template<class T, class Container>
auto stack_pusher(std::stack<T, Container>& stack)

    return push_iterator<std::stack<T, Container>>(stack);


int main()

    using namespace std;

    // construct an initial vector
    vector<int> init  7,6 ;

    // construct a stack using a copy of the initial vector's elements
    // note that the stack's storage is automatically deduced
    stack<int> stack1   begin(init), end(init)  ;

    // construct a stack directly from a container initialises with an initialiser list
    stack<int> stack2   3,4,5  ;

    // another vector
    vector<int> myvector  1, 2, 3, 4, 5, 6, 7, 8 ;

    // copy vector onto stack using a forward iterator
    copy(begin(myvector),
         end(myvector),
         stack_pusher(stack1));

    // copy vector onto stack using a reverse iterator
    copy(rbegin(myvector),
         rend(myvector),
         stack_pusher(stack2));

    // display the stacks
    while (stack1.size() or stack2.size())
    
        // function to encode an optional T as a string
        auto encode = [](const auto& opt)
        
            return opt ? std::to_string(opt.value()) : std::string("*");
        ;

        // function to pop a value from a stack if it's not empty.
        // return an optional
        auto maybe_pop = [](auto& stack)
        
            using element_type = std::decay_t<decltype(stack.top())>;
            boost::optional<element_type> result;
            if (stack.size()) 
                result = stack.top();
                stack.pop();
            
            return result;
        ;

        cout
        << encode(maybe_pop(stack1))
        << "\t"
        << encode(maybe_pop(stack2)) << endl;
    

    return 0;

【讨论】:

【参考方案3】:

std::stack 是一个奇怪但可破解的容器:

#include<vector>
#include<stack>

struct A;

template<class T>
struct mystack : std::stack<T>
    decltype(auto) c()return std::stack<T>::c;
;

int main()
    std::vector<A>  m_vec;

    mystack<A>   m_stack;
    m_stack.c().assign(m_vec.begin(), m_vec.end());


#include<vector>
#include<stack>

struct A;

template<class... T>
struct mystack : std::stack<T...>
    decltype(auto) container()return std::stack<T...>::c;
;

template<class... T>
decltype(auto) container(std::stack<T...>& s)return static_cast<mystack<T...>&>(s).container();

int main()
    std::vector<A>  m_vec;

    std::stack<A>   m_stack;
    container(m_stack).assign(m_vec.begin(), m_vec.end());

【讨论】:

【参考方案4】:

请参阅 this question 了解允许在堆栈上使用 std::copy 的方法,但开箱即用,没有比调用 push 的循环更明显的方法了。

至于性能,唯一的判断方法就是衡量它。 (代码首先要清晰和正确,然后担心速度。)

【讨论】:

以上是关于将元素从 std::vector 复制到 std::stack c++的主要内容,如果未能解决你的问题,请参考以下文章

std::vector emplace_back 可以从向量本身的元素复制构造吗?

如何在不导致复制的情况下将 char 数据附加到 std::vector

将 std::stack 复制到 std::vector

将 Cv::Mat 的数据存储在 std::vector 中

将 std::vector 复制到 qvector

如何在不循环的情况下将数组的内容复制到 C++ 中的 std::vector?