Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+中获取索引+;11 foreach循环_C++_C++11_Foreach - Fatal编程技术网

C++ 在C+中获取索引+;11 foreach循环

C++ 在C+中获取索引+;11 foreach循环,c++,c++11,foreach,C++,C++11,Foreach,在C++11 foreach循环中,是否有一种方便的方法来获取当前容器项的索引,如python中的enumerate: for idx, obj in enumerate(container): pass 我可以想象一个迭代器也可以返回索引或类似的内容 当然我可以有一个计数器,但迭代器通常不能保证它们在容器上迭代的顺序。如果需要索引,那么传统的for就可以很好地工作 for (int idx=0; idx<num; ++idx) { // do stuff } for(int

在C++11 foreach循环中,是否有一种方便的方法来获取当前容器项的索引,如python中的
enumerate

for idx, obj in enumerate(container):
    pass
我可以想象一个迭代器也可以返回索引或类似的内容


当然我可以有一个计数器,但迭代器通常不能保证它们在容器上迭代的顺序。

如果需要索引,那么传统的for就可以很好地工作

for (int idx=0; idx<num; ++idx)
{
// do stuff
}

for(int idx=0;idx可以在此处找到所需功能的良好实现:

背后的想法是,您使用一个自定义迭代器构建一个包装器结构,该迭代器进行计数。下面是一个非常简单的示例性实现来说明这一想法:

#include <iostream>
#include <vector>
#include <tuple>

// Wrapper class
template <typename T>
class enumerate_impl
{
public:
    // The return value of the operator* of the iterator, this
    // is what you will get inside of the for loop
    struct item
    {
        size_t index;
        typename T::value_type & item;
    };
    typedef item value_type;

    // Custom iterator with minimal interface
    struct iterator
    {
        iterator(typename T::iterator _it, size_t counter=0) :
            it(_it), counter(counter)
        {}

        iterator operator++()
        {
            return iterator(++it, ++counter);
        }

        bool operator!=(iterator other)
        {
            return it != other.it;
        }

        typename T::iterator::value_type item()
        {
            return *it;
        }

        value_type operator*()
        {
            return value_type{counter, *it};
        }

        size_t index()
        {
            return counter;
        }

    private:
        typename T::iterator it;
        size_t counter;
    };

    enumerate_impl(T & t) : container(t) {}

    iterator begin()
    {
        return iterator(container.begin());
    }

    iterator end()
    {
        return iterator(container.end());
    }

private:
    T & container;
};

// A templated free function allows you to create the wrapper class
// conveniently 
template <typename T>
enumerate_impl<T> enumerate(T & t)
{
    return enumerate_impl<T>(t);
}



int main()
{
    std::vector<int> data = {523, 1, 3};
    for (auto x : enumerate(data))
    {
        std::cout << x.index << ": " << x.item << std::endl;
    }
}
#包括
#包括
#包括
//包装类
模板
类枚举\u impl
{
公众:
//迭代器的运算符*的返回值
//是你将在for循环中得到的
结构项
{
尺寸指数;
typename T::value_type&item;
};
类型定义项目值\u类型;
//具有最小接口的自定义迭代器
结构迭代器
{
迭代器(类型名T::迭代器,大小T计数器=0):
它(_it),计数器(counter)
{}
迭代器运算符++()
{
返回迭代器(++it,++计数器);
}
布尔运算符!=(迭代器其他)
{
归还它!=其他。它;
}
typename T::迭代器::值\类型项()
{
归还它;
}
值类型运算符*()
{
返回值_type{counter,*it};
}
大小索引()
{
返回计数器;
}
私人:
类型名T::迭代器;
尺寸计数器;
};
枚举impl(T&T):容器(T){
迭代器begin()
{
返回迭代器(container.begin());
}
迭代器结束()
{
返回迭代器(container.end());
}
私人:
T&container;
};
//模板化的自由函数允许您创建包装器类
//方便地
模板
枚举(T&T)
{
返回枚举impl(t);
}
int main()
{
向量数据={523,1,3};
用于(自动x:枚举(数据))
{

std::cout一个简单的解决方案怎么样

int counter=0;
for (auto &val: container)
{
    makeStuff(val, counter);

    counter++;
}
通过添加作用域,可以使在计数器后添加代码变得更“困难”:

int counter=0;
for (auto &val: container)
{{
    makeStuff(val, counter); 
}counter++;}
正如@graham.reeds所指出的,正常的
for
循环也是一种解决方案,其速度可能与以下方法一样快:

int counter=0;
for (auto it=container.begin(); it!=container.end(); ++it, ++counter)
{
    makeStuff(val, counter);
}
最后,使用算法的另一种方法:

int counter = 0;
std::for_each(container.begin(), container.end(), [&counter](int &val){ 
    makeStuff(val, counter++);
});
注:量程循环和正常循环之间的顺序由标准6.5.4保证。这意味着计数器能够与容器中的位置一致


如果您可以访问Boost,其范围适配器可以如下使用:

using namespace boost::adaptors;

for (auto const& elem : container | indexed(0))
{
    std::cout << elem.index() << " - " << elem.value() << '\n';
}
使用名称空间boost::adapters;
用于(自动常量和元素:容器|索引(0))
{

std::coutC++17和结构化绑定使它看起来不错-当然比一些丑陋的可变lambda更好,它带有一个本地的
[i=0](元素&)可变的
,或者我在承认可能不是所有东西都应该被塞进
中之前所做的任何事情
等。-而不是其他需要计数器的解决方案,计数器的作用域不在
循环中

for(auto[it,end,i]=std::tuple{container.cbegin(),container.cend(),0};
它!=结束;++it,++i)
{
//同时需要“它”和“我”的东西
}
如果您经常使用此模式,则可以将其设置为通用模式:

template <typename Container>
auto
its_and_idx(Container&& container)
{
    using std::begin, std::end;
    return std::tuple{begin(container), end(container), 0};
}

// ...

for (auto [it, end, i] = its_and_idx(foo); it != end; ++it, ++i)
{
    // something
}
模板
汽车
its_和_idx(容器和容器)
{
使用std::begin、std::end;
返回std::tuple{begin(container),end(container),0};
}
// ...
for(auto[it,end,i]=its_和_idx(foo);it!=end;++it,++i)
{
//某物
}

C++标准提案建议添加
视图::enumerate
,这将提供一个范围视图,该视图向迭代它的用户提供对元素的引用和元素的索引

我们提出了一个视图
enumerate
,其值类型为
struct
,有两个成员
index
value
,分别表示调整范围内元素的位置和值

[……]

此特征以Python、Ru锈、Go(在语言中)的形式存在,在许多C++库中:<代码> Ranges -V3,<>代码>愚蠢> <代码>,代码> Boo::范围< /COD>(<代码>索引< /C> >) 这一特征的存在与否是反复出现的问题的主题


嘿,看!我们很有名。

不,但使用boost并不难。Range的
zip
和boost的
计数迭代器一起达到这个目的。复制到某个东西,答案是自己计数。这个答案怎么样:听起来不错,但它只适用于顺序容器,而不适用于关联容器。对于associTive容器您需要的是键,而不是索引。@EdChum:关联容器的迭代器已经返回键和值。这可能会很慢。例如,可能是链表,但没有提到性能,也没有提到链表。为什么迭代器在链表上会更快?因为它可以在内部保存当前节点和值从那里开始。不需要随机访问。因为链表不支持随机访问。而且它不适用于无序容器,例如
set
map
当您使用迭代器时,可以使用
std::distance(container.begin(),it)
而不是计数器变量。@sigalor:根据迭代器的类型,std::distance可能是O(n),它不如计数器(O(k))好.@AdrianMail您的上一个示例似乎没有增加计数器。谢谢,应该现在修复。@sigalor是的,但这可以说是浪费,特别是当有很多元素和/或容器是迭代器算法昂贵的容器时。警告:信不信由你,如果