C ++:进行切片时迭代器的约定,特别是访问最后一个元素并最终将其删除

C++ : Convention on iterator when doing slicing, especially for accessing to the last element and eventually remove it

我有以下函数可以计算向量所有元素的总和:

double arraySum(vector<double> const &v) {

    double initial_sum  = 0.0;
    return accumulate(v.begin(), v.end(), initial_sum);
}

从另一个角度来看,如果我有以下列表并且我想删除最后一个字符串,我会这样做:

   param_chain_A = {"wm", "wde", "wb", "w0", "wa", "h", "ns", "s8", "gamma", "A_IA", "n_IA", "B_IA", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "b10", "b11"};

    if (model == "S") {
      param_chain_A.erase(param_chain_A.end()-1);
    }

如您所见,在第一个示例中,我使用 v.end() 作为向量的最后一个元素,使用 param_chain_A.end()-1 作为列表的最后一个元素。

我只是想更好地了解如何识别向量的最后一个元素和带有关键字的列表 .end()

来自this link,据说:

"You're trying to count down j to zero, and imageDataVector.end() - 0 is not a valid iterator. In the standard C++ library containers, the end iterator points one past the last element, not at the last element."

所以我的问题很简单:访问向量的最后一个元素(最终删除它)和列表的最后一个元素有区别吗?

如果没有,如何处理这两种情况(删除最后一个元素)

我有第三个例子,我想提取初始向量的子向量:

// Slice for arrays like python syntax
vector<double> slice(vector<double> const &v, int m, int n)
{
    vector<double>::const_iterator first = v.begin() + m;
    vector<double>::const_iterator last = v.begin() + n;

    vector<double> vec(first, last);
    return vec;
}

在这种情况下,我提取了从 m+1 element 开始直到包含向量 vn+1 element 的向量,不是吗?在这里,我不使用 .end().

我必须表明我想得到一个std-c++11约定(如果可能的话)。

PS: 看到有.rbegin()迭代器可以直接访问最后一个元素,但是用[=22是不是有问题=] 而不是 std-c++11 版本,我的意思是,对于基本的科学代码(我不会在我的代码中将 C++ 的 "object" 逻辑推得太远,只需使用 class class典型的属性和方法)。

我相信您想访问向量和列表的最后一个元素。有成员方法:

int main()
{
    std::list<char> letters {'a', 'b', 'c', 'd', 'e', 'f'};
    std::vector<int> numbers {1,2,3,4,5,6,7,8};

    if (!letters.empty()) {
        std::cout << "The last character is: " << letters.back() << '\n';
    }  
    if (!numbers.empty()) {
        std::cout << "The last numbrer is: " << numbers.back() << std::endl;
    }
}

或者,您可以使用 std::prev、

auto it = numbers.end();
if (it != numbers.begin()){
    std::cout << *prev(it) << std::endl;
} 

As you can see, in the first example, I used v.end() for the last element of a vector

不,你没有。您使用 v.end() 表示序列的 end。这与最后一个元素不同。

C++ 中的范围(按照惯例)是 half-open。就像使用 for(int i = 0; i < 10; ++i) 循环一样;范围是 0 到 10,但是循环永远不会看到 i 何时获得值 10。i 只假定值 0 到 9。10 仅用于确定何时终止循环;它不是循环中的元素。

任何 "end" 迭代器也是如此;从某种意义上说,它是一个有效的迭代器,您可以从中减去它(如果迭代器允许的话)。但它不是一个可取消引用的迭代器;如果你尝试做 *v.end(),你会得到未定义的行为。它只是定义何时到达迭代器定义的序列的 "end"。

使用半开范围允许您指定一个空范围,其中开始条件和结束条件都相同。

I extract the vector beginning at the m+1 element up to including n+1 element of vector v, don't I ?

不,你不知道。

假设基于零的索引的标准 C++ 约定,新向量的开头将包含旧向量的第 m 个元素。新向量中的最后一个元素将包含旧向量的第 n-1 个元素,因为 终止 复制过程的迭代器是指向第 n 个的迭代器元素(假设有第 n 个元素;不必有,只要有第 n-1 个元素)。