我正在迭代一个向量,需要迭代器当前指向的下标。下列方法的优缺点是什么?
It - vec.begin() std::距离(vec.begin ())
我正在迭代一个向量,需要迭代器当前指向的下标。下列方法的优缺点是什么?
It - vec.begin() std::距离(vec.begin ())
我更喜欢std::distance(vic .begin(),它),因为它将允许我在没有任何代码更改的情况下更改容器。例如,如果你决定使用std::list而不是std::vector,后者不提供随机访问迭代器,你的代码仍然会被编译。因为std::distance根据迭代器的特性选择最佳方法,所以你也不会有任何性能下降。
根据http://www.cplusplus.com/reference/std/iterator/distance/,由于vecc .begin()是一个随机访问迭代器,distance方法使用-操作符。
因此,从性能的角度来看,答案是相同的,但是如果任何人都必须阅读和理解您的代码,那么使用distance()可能更容易理解。
我更喜欢它- vvector .begin(),正是因为Naveen给出的相反原因:所以如果你将vector更改为列表,它就不会编译。如果你在每次迭代中都这样做,你可以很容易地把O(n)算法变成O(n²)算法。
另一种选择是,如果在迭代期间不在容器中跳来跳去,则将索引保留为第二个循环计数器。
注意:它是容器迭代器的常用名称,std::container_type::iterator it;。
正如本叔叔和内文所表明的那样,两者都有很好的理由。哪一种“更好”取决于您想要的行为:您是希望保证常量时间行为,还是希望在必要时回落到线性时间?
它- vvector .begin()花费常数时间,但operator -仅在随机访问迭代器上定义,因此,例如,对于列表迭代器,代码根本无法编译。
Std::distance(vecc .begin(), it)适用于所有类型的迭代器,但如果用于随机访问迭代器,则只会是一个常量时间操作。
两者都不是“更好”。用你需要的那个。
我只会对std::vector使用-变体——它的意思很清楚,操作的简单性(不超过指针减法)是由语法表示的(另一方面,距离听起来像毕达哥拉斯第一次阅读,不是吗?)正如UncleBen指出的那样,-在vector被意外更改为list的情况下也充当静态断言。
我也认为这是更普遍的-虽然没有数字可以证明。主实参:it - vic .begin()在源代码中更短-更少的输入工作,更少的空间消耗。很明显,你的问题的正确答案归结为品味的问题,这也可以是一个有效的论点。
如果你已经限制/硬编码你的算法只使用std::vector::iterator和std::vector::iterator,那么你最终使用哪种方法并不重要。你的算法已经具体化了,选择其中一个会有任何不同。它们做的事情完全一样。这只是个人喜好的问题。我个人会使用显式减法。
另一方面,如果您希望在算法中保留更高程度的通用性,即允许将来某一天它可能应用于其他迭代器类型,那么最佳方法取决于您的意图。这取决于你希望在这里使用的迭代器类型有多严格。
如果使用显式减法,则算法将被限制在相当狭窄的一类迭代器中:随机访问迭代器。(这是你现在从std::vector中得到的) 如果使用distance,算法将支持更广泛的迭代器类:输入迭代器。
Of course, calculating distance for non-random-access iterators is in general case an inefficient operation (while, again, for random-access ones it is as efficient as subtraction). It is up to you to decide whether your algorithm makes sense for non-random-access iterators, efficiency-wise. It the resultant loss in efficiency is devastating to the point of making your algorithm completely useless, then you should better stick to subtraction, thus prohibiting the inefficient uses and forcing the user to seek alternative solutions for other iterator types. If the efficiency with non-random-access iterators is still in usable range, then you should use distance and document the fact that the algorithm works better with random-access iterators.
我刚刚发现了这个:https://greek0.net/boost-range/boost-adaptors-indexed.html
for (const auto & element : str | boost::adaptors::indexed(0)) {
std::cout << element.index()
<< " : "
<< element.value()
<< std::endl;
}
除了int float string等,当使用div . types时,你可以将额外的数据放入.second,例如:
std::map<unsigned long long int, glm::ivec2> voxels_corners;
std::map<unsigned long long int, glm::ivec2>::iterator it_corners;
or
struct voxel_map {
int x,i;
};
std::map<unsigned long long int, voxel_map> voxels_corners;
std::map<unsigned long long int, voxel_map>::iterator it_corners;
when
long long unsigned int index_first=some_key; // llu in this case...
int i=0;
voxels_corners.insert(std::make_pair(index_first,glm::ivec2(1,i++)));
or
long long unsigned int index_first=some_key;
int index_counter=0;
voxel_map one;
one.x=1;
one.i=index_counter++;
voxels_corners.insert(std::make_pair(index_first,one));
使用正确的||结构,你可以把任何东西放在。second中,包括在进行插入时递增的索引号。
而不是
it_corners - _corners.begin()
or
std::distance(it_corners.begin(), it_corners)
后
it_corners = voxels_corners.find(index_first+bdif_x+x_z);
索引很简单:
int vertice_index = it_corners->second.y;
当使用glm::ivec2类型时
or
int vertice_index = it_corners->second.i;
对于结构数据类型