std :: vector, построенный с initializer_list, не ведущий себя как ожидалось - PullRequest
1 голос
/ 08 октября 2019

Следующий код скомпилирован в OpenSUSE Tumbleweed с GCC 9.2.1 20190903 ревизия 275330

#include <vector>
#include <iostream>

int main()
{
    std::vector<double> datos = {1, 2, 3, 4, 5, 6};

    std::cout << "DEBUG: vector ";
    for (auto d : datos)
        std::cout << datos[d] << ' ';
    std::cout << std::endl;
}

Вывод

DEBUG: vector 2 3 4 5 6 0

Но я ожидал

DEBUG: vector 1 2 3 4 5 6

Еще для этого другого кода:

#include <vector>
#include <iostream>

int main()
{
    std::vector<double> datos = {1, 1, 2, 3, 4, 5};

    std::cout << "DEBUG: vector ";
    for (auto d : datos)
        std::cout << datos[d] << ' ';
    std::cout << std::endl;
}

Вывод такой, как ожидалось:

DEBUG: vector 1 1 2 3 4 5

Командная строка g++-9 test.cc

Я что-то упустил? Это ошибка в компиляторе?

Ответы [ 3 ]

2 голосов
/ 08 октября 2019

Значение переменной d в цикле на основе диапазона для

for (auto d : datos)
        std::cout << datos[d] << ' ';

не является индексом в векторе. Это значение текущего элемента вектора

Просто используйте

for (auto d : datos)
        std::cout << d << ' ';

Для этого вектора

std::vector<double> datos = {1, 1, 2, 3, 4, 5};

вы получили ожидаемый результат, потому что

datos[datos[1]] равно 1, то есть он равен этому элементу

std::vector<double> datos = {1, 1, 2, 3, 4, 5};
                               ^^^

datos[datos[1]] снова дает тот же элемент.

datos[datos[2]] равен 2 и т. Д. on.

Если вы, например, измените вектор, например

std::vector<double> datos = { 5 };

, то у вас будет неопределенное поведение, потому что datos[datos[2]] пытается получить доступ к памяти за пределами выделенной памяти для элементов вектора.

Без углубления в детали этот цикл

for (auto d : datos)
    std::cout << d << ' ';

фактически эквивалентен следующему

for ( auto first = std::begin( datos ); first != std::end( datos ); ++first )
{
    auto d = *first;
    std::cout << d << ' ';
}
1 голос
/ 08 октября 2019

Для цикла for на основе диапазона элемент уже является целым числом.

Либо используйте for цикл на основе диапазона правильно

for (auto d : datos)
    std::cout << d << ' ';

, либо используйте традиционный цикл

for (size_t d = 0; d < datos.size(); ++d)
    std::cout << datos[d] << ' ';
1 голос
/ 08 октября 2019

Я что-то упустил?

Вы смешали диапазон, основанный на циклах, с индексацией в векторе - вместо этого выберите один стиль. Исправлен пример с основанным на диапазоне циклом for (который позволяет напрямую перебирать элементы диапазона):

for (auto d : datos)
    std::cout << d << ' ';

Пример с ручными индексами:

for (std::size_t i = 0; i < datos.size(); ++i)
    std::cout << datos[i] << ' ';
...