【问题标题】:How to get a 'stack based' std::stack? (with fixed max size)如何获得“基于堆栈”的 std::stack? (具有固定的最大尺寸)
【发布时间】:2019-10-08 14:06:26
【问题描述】:

根据std::stack参考:

用于存储元素的底层容器的类型。 容器必须满足 SequenceContainer 的要求。 此外,它必须提供以下功能与通常的 语义:

back()
push_back()
pop_back() 

标准容器 std::vector、std::deque 和 std::list 满足 这些要求。默认情况下,如果没有指定容器类 特定的堆栈类实例化,标准容器 使用 std::deque。

所有这些都是基于堆的容器。

以下实际编译():

std::stack<int, std::array<int, 12> > stack_of_months;

直到push 被调用。

是否有一些技巧可以轻松包装 std::array 以支持这些方法,以便可以在堆栈中使用它?

【问题讨论】:

  • 否,因为它不支持push 函数。 vector 怎么了?
  • 好的,假设您可以使用std::array 来执行此操作。如果你在一个完整的堆栈上调用 push 会发生什么?抛出异常,底部元素被移除等?
  • @ChrisMM 向量没有什么问题——我喜欢向量——但假设你需要一个有限的基于堆栈的堆栈
  • 将数据存储在“堆栈上”的对象在 C++ 中是隐式固定大小的。 std::array 不能增长或缩小。如果您知道需要容纳的最大大小或愿意任意设置一个,您也许可以实现自己的容器。但是在堆栈上存储大量数据通常是不明智的,这是一种有限的资源。这样做很容易耗尽堆栈空间,而且无法恢复。
  • @darune 也许将std::vector 与基于堆栈的分配器一起使用可能对您有用。但是考虑一下我之前关于在堆栈上存储大数据的警告。

标签: clang c++ stack c++17


【解决方案1】:

你应该可以使用Boost的static_vector:

static_vector 是一个序列容器,类似于具有可以改变大小的连续存储,以及静态分配、低开销和固定容量。

一个工作示例:

std::stack<int, boost::container::static_vector<int, 4>> s;
s.push(1);
s.push(2);
s.push(3);
s.push(4);
// s.push(5); // would throw

@PaulMcKenzie 是的,它使用堆栈作为存储(如果对象本身存储在堆栈中,当然):

static_vector 中的元素数量可以动态变化,直至达到固定容量因为元素存储在对象本身中类似于数组。

现场演示:https://wandbox.org/permlink/Gi40FrB0yX8dIwfA。

【讨论】:

  • 好的,我看到它有一个模板参数dtl::static_storage_allocator&lt; Value, Capacity &gt;,这表明它正在使用静态存储分配器。
  • @PaulMcKenzie 我认为您无需探索源代码即可找到答案。文档里写得很清楚,基本上就是这个容器的主要用途。
  • 没有阅读源代码——它就在你第二行链接到的站点中。
  • @PaulMcKenzie 好的。我的观点是分配器类来自某个实现命名空间dtl,因此,IMO,最好阅读文档而不是根据某个类名或其实现来假设行为。
【解决方案2】:

将std::array 包装成std::stack 可用的东西并不难,您只需要跟踪有多少元素被推送和弹出:

#include <array>
#include <stack>
#include <iostream>

template < typename T, size_t Size >
struct static_vector
{
  using value_type = T;
  using reference = T&;
  using const_reference = const T &;
  using size_type = size_t;

  static_vector()
    : size( 0 )
  {
  }

  std::array< T, Size > data;
  size_t size;

  void push_back( const_reference value )
  {
    data.at( size ) = value;
    size++;
  }

  void pop_back()
  {
    if ( size == 0 )
    {
      throw std::runtime_error( "empty" );
    }
    size--;
  }

  const_reference back() const
  {
    if ( size == 0 )
    {
      throw std::runtime_error( "empty" );
    }
    return data[ size - 1 ];
  }

  reference back()
  {
    if ( size == 0 )
    {
      throw std::runtime_error( "empty" );
    }
    return data[ size - 1 ];
  }
};

int main()
{
  std::stack< int, static_vector< int, 4 > > stack;
  stack.push( 1 );
  std::cout << stack.top() << "\n";
  stack.push( 2 );
  std::cout << stack.top() << "\n";
  stack.pop();
  std::cout << stack.top() << "\n";
  stack.pop();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-17
    • 1970-01-01
    • 2013-02-14
    • 1970-01-01
    • 2021-10-22
    • 2016-03-18
    相关资源
    最近更新 更多