我有一个对象向量,并使用range-for循环迭代它.我用它来打印对象的函数,如下所示:
vector<thisObject> storedValues;
//put stuff in storedValues
for(auto i:storedValues)
{
cout<<i.function();
}
Run Code Online (Sandbox Code Playgroud)
但我也想打印索引.我想要的输出是:
1: value
2: value
//etc
Run Code Online (Sandbox Code Playgroud)
我打算只使用我每次增加的计数器,但这看起来非常低效.有没有更好的办法?
Ker*_* SB 31
你不能.该指数是一个特定的概念,以一个矢量,而不是一个集合的一般属性.另一方面,基于范围的循环是迭代任何集合的每个元素的通用机制.
如果您确实想要使用特定容器实现的详细信息,只需使用普通循环:
for (std::size_t i = 0, e = v.size(); i != e; ++i) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
重复一点:基于范围的循环用于操作任何集合的每个元素,集合本身无关紧要,并且循环体内从不提及容器.它只是您工具箱中的另一个工具,并且您不必将其用于绝对一切.相反,如果您想要改变集合(例如删除或随机元素),或者使用有关集合结构的特定信息,请使用普通循环.
Tha*_*esy 12
我敢肯定有些人不会喜欢这个,但我已经创建了一个预处理器宏,以(IMO)相对干净的方式为你处理这个问题:
#define for_indexed(...) for_indexed_v(i, __VA_ARGS__)
#define for_indexed_v(v, ...) for(bool _i_ = true, _break_ = false; _i_;) for(size_t v = 0; _i_; _i_ = false) for(__VA_ARGS__) if(_break_) break; else for(bool _j_ = true; _j_;) for(_break_ = true; _j_; _j_ = false) for(bool _k_ = true; _k_; v++, _k_ = false, _break_ = false)
Run Code Online (Sandbox Code Playgroud)
用法示例:
std::vector<int> v {1, 2, 3};
for_indexed (const auto& item : v) {
if (i > 0) std::cout << ", ";
std::cout << i << ": " << item;
}
Run Code Online (Sandbox Code Playgroud)
要使用不同的循环变量:
for_indexed_v (my_cool_counter, const auto& item : v) ...
Run Code Online (Sandbox Code Playgroud)
我已经仔细检查了,这个额外的循环内容都被优化了-O1或更高.你留下了一个很好的,易于阅读的循环语法.
额外奖励:这也适用于经典iterator风格的循环.(虽然你也可以使用std::distance(begin, it).)
更新日期:28/05/2017:Made break;语句正常工作
更新28/01/2019:for输入宏名称,以便该单词indexed是有效的变量名称.我怀疑for_indexed会引起任何冲突.
您可以使用range-v3的enumerate视图:
std::vector<thisObject> storedValues;
for (auto const& [idx, value] : storedValues | ranges::views::enumerate) {
std::cout << idx << ": " << value << '\n';
}
Run Code Online (Sandbox Code Playgroud)
C++20 将在 range-for 循环中引入额外的初始化:
std::vector<thisObject> storedValues;
for (size_t idx = 0; auto value : storedValues) {
std::cout << idx << ": " << value << '\n';
++idx;
}
Run Code Online (Sandbox Code Playgroud)
使用range-v3。Range-v3是由ISO C ++委员会成员Eric Niebler设计和实现的下一代范围库,并且打算并希望在将来与C ++标准合并。
通过使用range-v3OP的问题可以轻松解决:
using ranges::v3::view::zip;
using ranges::v3::view::ints;
for(auto &&[i, idx]: zip(storedValues, ints(0u))){
std::cout << idx << ": " << i.function() << '\n';
}
Run Code Online (Sandbox Code Playgroud)
您将需要一个支持C ++ 17或更高版本的编译器来编译这段代码,这不仅用于结构化绑定语法,而且还用于以下事实:返回值的函数类型begin和end返回值的函数ranges::v3::view::zip不同。
您可以在此处看到在线示例。的文档range-v3位于此处,源代码本身位于此处。如果您使用的是MSVC编译器,也可以在这里查看。
小智 5
老实说,这很简单,只需弄清楚你可以减去地址:)
&i将引用内存中的地址,并且它会从一个索引到另一个索引递增 4,因为它保存了定义的向量类型的整数。现在&values[0]引用了第一点,当你减去 2 个地址时,两者之间的差将分别是 0,4,8,12,但实际上它减去了整数类型的大小,通常是 4 个字节。所以对应起来 0 = 0th int,4 = 1st int, 8 = 2nd int, 12 = 3rd int
这是一个向量
vector<int> values = {10,30,9,8};
for(auto &i: values) {
cout << "index: " << &i - &values[0];
cout << "\tvalue: " << i << endl;
}
Run Code Online (Sandbox Code Playgroud)
这是一个常规数组,几乎是一样的东西
int values[]= {10,30,9,8};
for(auto &i: values) {
cout << "index: " << &i - &values[0];
cout << "\tvalue: " << i << endl;
}
Run Code Online (Sandbox Code Playgroud)
注意这是针对C++11的,如果你使用g++,记得使用-std=c++11参数进行编译
| 归档时间: |
|
| 查看次数: |
14756 次 |
| 最近记录: |