【问题标题】:Error when adding int elements from a vector c++从向量 c++ 添加 int 元素时出错
【发布时间】:2016-04-26 20:53:20
【问题描述】:

我有这个代码:

// Example program
#include <iostream>
#include <vector>
#include <algorithm>

int main()
{
    std::vector<int> test_vector;
    std::vector<int>::iterator v;
    int test = 1;
    int sum = 0;

    for (int i = 0; i < 10; i++) {
        test = test * 2;
        test_vector.push_back(test);
    }

    for (v = test_vector.begin(); v < test_vector.end(); v++) {
        std::cout << *v << " ";
    }

    std::cout << std::endl;

    std::reverse(test_vector.begin(), test_vector.end());

    for (v = test_vector.begin(); v < test_vector.end(); v++) {
        std::cout << *v << " ";
    }

    std::cout << std::endl;

    for (v = test_vector.begin(); v < test_vector.end(); ++v) {
        sum = sum + test_vector[*v];
        std::cout << sum << " ";
    }

    return 0;
}

这很简单,我有一个向量,用一些元素填充它,而不是反向并最终尝试添加所有元素。

输出是这样的:

2 4 8 16 32 64 128 256 512 1024 
1024 512 256 128 64 32 16 8 4 2 
0 0 0 0 0 0 0 4 68 324  

问题是:在sum 所在的最后一个循环中我做错了什么?

我希望它是 1024 + 512 + 256 之类的东西;

【问题讨论】:

  • test_vector[*iterator]; 是一个很大的代码味道
  • 你拥有的是UB,你应该拥有sum = sum + *v;而不是sum = sum + test_vector[*v];
  • 迭代器不是索引。

标签: c++ vector stl iterator


【解决方案1】:

使用test_vector[*v]; 将超出范围并导致undefined behavior

这应该改为:

for (v = test_vector.begin(); v < test_vector.end(); ++v) {
    sum = sum + *v;
    std::cout << sum << " ";
}

sum += *v; 以获得更短的版本。

【讨论】:

    【解决方案2】:

    向量只有 10 个元素

    for (int i = 0; i < 10; i++) {
                    ^^^^^^
        test = test * 2;
        test_vector.push_back(test);
    }
    

    所以向量的有效索引范围是0-9

    但是在这个循环中

    for (v = test_vector.begin(); v < test_vector.end(); ++v) {
        sum = sum + test_vector[*v];
                               ^^^^^
        std::cout << sum << " ";
    }
    

    此表达式test_vector[*v] 中的索引值可能超出向量的有效索引范围。

    你可以写例如

    for (v = test_vector.begin(); v < test_vector.end(); ++v) {
        sum = sum + *v;
                    ^^^^
        std::cout << sum << " ";
    }
    

    或者你甚至可以写

    for (v = test_vector.begin(); v < test_vector.end(); ++v) {
        sum = sum + v[0];
                    ^^^^
        std::cout << sum << " ";
    }
    

    如果您的编译器支持基于范围的 for 循环,那么编写起来会更简单

    for ( int x : test_vector ) {
        sum = sum + x;
        std::cout << sum << " ";
    }
    

    考虑到运算符

    for (v = test_vector.begin(); v != test_vector.end(); ++v) {
                                  ^^^^^^^^^^^^^^^^^^^^^^
    

    【讨论】:

    • v[0] aka iterator[index] 是有问题的(如果迭代器 id 没有指针,则不起作用)
    • @DieterLücking 该运算符适用于任何随机访问迭代器。
    • 谢谢你的课(有用吗?)
    • @DieterLücking 我自己从来没见过。:) 我只提到了这个问题。:)
    • @DieterLücking 直到现在我都没有写过 C++ 程序,因为我失业了。:)
    【解决方案3】:
    for (v = test_vector.begin(); v < test_vector.end(); ++v) {
            sum = sum + *v;
            std::cout << sum << " ";
    }
    

    是正确的代码。

    或者,相同但更短且更 C++11 风格:

    for (const int item: test_vector) {
        sum += item;
        std::cout << sum << " ";
    }
    

    甚至

    sum = std::accumulate(test_vector.begin(), test_vector.end(), 0);
    

    【讨论】:

      【解决方案4】:

      您的代码test_vector[*v] 不正确。你在那里做的是你正在取消引用一个迭代器并得到一个整数(因为你的向量是一个整数向量)。现在,您使用这个整数作为索引访问一个元素,当然,到达随机内存位置,超出数组边界并触发未定义的行为。

      您在其他两个循环中正确使用了迭代器,所以我认为这只是一个错字。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-15
        • 2014-04-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多