将元素从 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