2014-09-19 97 views
6

设A为std::vector<double>,end()迭代器上的指针运算

这是明确的吗?

if(!A.empty()) 
    std::vector<double>::iterator myBack = A.end() - 1; 

是在end迭代器只对等式和不等式检查好?或者只要我留在容器中,我可以执行一些指针算术?

在我的平台上,此代码工作。我想知道这是否便携。

+3

这很好,你也可以使用'A.rbegin()'。 – perreal 2014-09-19 07:28:36

+3

它是* iterator *算术。它应该可以用于双向迭代器(如'std :: vector :: iterator')。 – Jarod42 2014-09-19 07:28:55

回答

5

这是完全有效的,因为vector::iterator是一个随机访问迭代器。您可以对其执行算术运算,并且不依赖于平台。

std::vector<double>::iterator it = A.end(); 
while (it != A.begin()){ 
    --it; //this will skip A.end() and loop will break after processing A.front() 
    //do something with 'it' 
} 

A.end()但是指理论过去最端部元件,因此它不指向一个元素,因此不应被解除引用。所以最好的做法是使用反向迭代器,而不是递减结束迭代器。

for(std::vector<double>::reverse_iterator it = A.rbegin(); it != A.rend(); ++it) { 
    //do something with 'it' 
} 

这两个循环做同样的事情,第二就是可以理解的,更清洁的方式来做到这一点。

+0

这两个循环不相同,第一个循环不会遍历'A.front()'。 – Jarod42 2014-09-19 07:48:57

+1

但我不认为'A.begin() - 1'是有效的。 – Jarod42 2014-09-19 08:00:18

4

几乎安全的,如果你留意的一些特殊情况:

A.end()给你一个迭代器表示位置刚好超过std::vector结束。您应该而不是试图取消引用它。

如果矢量具有零元素,则A.end() - 1而不是明确定义的。在所有其他情况下,只要您处于容器边界内,就可以确实执行指针运算。请注意,该标准保证std::vector数据是连续的,并且与包含类型的C++数组完全相同。唯一的例外是std::vector<bool>,由于标准规定的紧包装专业化,其行为不同。 (注意sizeof(bool)而不是保证有一个标准的特定值)。

如果我是你,我会使用A.rbegin()访问最右边的元素并在继续之前检查返回值并坚持迭代器公式。忘记std::vector<bool>专业化非常容易。

+0

我不确定'bool'的情况。这个迭代器 - 不是指针 - 算术,就像@ Jarod42指出的那样?难道这不应该使它完全安全并且为'std :: vector '定义好吗? – 2014-09-19 07:40:49

+0

如果一个'std :: vector '有3个元素,那么我不相信如果sizeof(bool)== sizeof(int)'定义了'A.end() - 1'。但我可能是错的。但是如果你把任何东西都扔到'布尔*'上,那你肯定会遇到麻烦。也许'bool'反向迭代器的一个重载运算符负责处理这个问题。简答:我不知道。我正在考虑在这个问题上给予奖励。 – Bathsheba 2014-09-19 07:41:44

+0

如果'std :: vector :: iterator'表现得像你说的那样,对向量的简单迭代就不起作用。只要你在迭代器上操作,' - 1'必须将它移动一个逻辑元素,而不是'sizeof(bool)'字节。我在http://ideone.com/2pAiE1上添加了一些代码,只要减法的结果在容器中,它就可以工作。你应该用'_GLIBCXX_DEBUG'(或者编译器的等价物)对它进行编译,当你超越边界时,它会对你咆哮。 – 2014-09-19 07:48:21