【问题标题】:Iterator or std::iota with regular C++ Array?带有常规 C++ 数组的迭代器或 std::iota?
【发布时间】:2020-12-23 14:38:38
【问题描述】:

有没有办法达到和这个一样的效果,

std::list<int> l(10);
std::iota(l.begin(), l.end(), -4);

有一个普通的int a[]

或者,以下是唯一的解决方法:

for (iterator itr = begin; itr != end; ++itr)
    /* ... visit *itr here ... */

【问题讨论】:

  • 只是std::iota( std::begin(a), std::end(a), -4 )。我的意思是,如果后者是“唯一的解决方法”,那么首先如何让这些迭代器与 for 循环?
  • 那是 O(1) 吗?对吗?
  • 为什么不呢?指向普通数组的迭代器只是指针。这似乎是 Cannot use .begin() or .end() on an array 的欺骗
  • ?什么意思?
  • 该数组的 std::beginstd::end 等效于 &amp;a[0]&amp;a[number_of_elements] (您可以永远使用它们)。迭代器的接口与指针的接口外观相同并非巧合。

标签: c++ c++11


【解决方案1】:

tl;dr:将数组包装在“span”中。

@idclev463035818 的answer 是最直接的做法。但是,如果您想在多个上下文中将数组视为标准库容器,请考虑将原始数组包装在跨度中,如下所示:

auto a_ = std::span{a};

span 是连续存储的轻量级引用类型。他们不拥有自己的数据,因此您无需复制数组或任何东西。您可以在此处阅读有关跨度的更多信息:

What is a "span" and when should I use one?

不管怎样,现在你可以写了:

std::iota(a_.begin(), a_.end(), -4);
for(x : a_) { do_stuff_with(x); }
auto c = std::ranges::count_if(a_, [](auto x) { return x > 3; });

等等。或许更重要的是,数组"decays" into a pointer如果你把它传递给另一个函数,那么你就不能再在上面使用std::begin()std::end()了; span 可以被传递,所以它更健壮。

但是 - std::span 仅在以 C++20 开头的标准中。在此之前,您可以使用 gsl-lite library 中的 span 实现,例如。

【讨论】:

  • for range based for loops a span不是必要的(godbolt.org/z/9ea1qE)否则很好的答案。还有好听的用户名:P
  • @idclev463035818:啊,我还没有意识到基于范围的 for 循环适用于数组。谢谢,已编辑。
【解决方案2】:

C++11 添加了std::beginstd::end。从那以后就没有区别了:

std::list<int> l(10);
std::iota(std::begin(l),std::end(l), -4);
int a[10];
std::iota(std::begin(a),std::end(a), -4);

【讨论】:

  • 我不是故意粗鲁,但是您的用户名有很长的数字序列,很难引用。
  • @einpoklum 用户名可以更改,我已经多次遇到用户名引用被破坏的情况,恕我直言,只有link 就足够了
  • 我的意思是,当我想说@idclev463whatever 时,但我不记得数字序列...
猜你喜欢
  • 1970-01-01
  • 2021-07-24
  • 1970-01-01
  • 1970-01-01
  • 2020-03-24
  • 2017-07-27
  • 1970-01-01
  • 2016-04-16
  • 1970-01-01
相关资源
最近更新 更多