Код хранит вектор как вектор <vector>, почему нет сообщения об ошибке?

Я работаю над фрагментом кода C++, оставленным предшественником, и он, по-видимому, хранит vector<long int> как vector<vector<long int>>. Код компилируется и запускается, но я не понимаю почему. Вот функция, которая сохраняет.

void setPotentialParameters(const int& seed, const int& nMax, const double& lambdaStd, const int fieldNum, potentialPars& par)
{
    gsl_rng * r = gsl_rng_alloc (gsl_rng_taus);
    gsl_rng_set (r, seed);
    par.nMaximum= nMax;
    par.fNum= fieldNum;
    for (int i=0; i<100; i++) gsl_ran_gaussian (r, lambdaStd);
    int counter=0;
    vector<long int> tempNs(fieldNum); //Defines tempNs as a vector<long int>
    for (long int i=0; i< (-0.2+pow(2*nMax+1, fieldNum)); i++) { 
        findPartition(i, fieldNum, 2*nMax+1, tempNs ); 
        for (int i = 0; i < tempNs.size(); i++) {
            tempNs[i] -= nMax;
        }
        if (goodPartition(tempNs, nMax)) {
            counter++;
            par.lambdas.push_back(abs( gsl_ran_gaussian (r, lambdaStd))); 
            par.nVals.push_back(tempNs); //Stores tempNs in nVals
            par.alphas.push_back(2*M_PI * gsl_rng_uniform (r));
        };
    };
};

И это структура, в которой хранится tempNs.

struct potentialPars{
    int nMaximum;
    int fNum;
    vector<double> lambdas;
    vector<vector<long int> >  nVals; //Defines nVals as a vector<vector<long int>>
    vector<double> alphas;
};

Я отметил три самые актуальные строки комментариями. tempNs имеет только один элемент (как видно из строки tempNs[i] -= nMax), что соответствует его определению как vector<long int>, но когда nVals вызывается в другом месте программы, он имеет два элемента, что также соответствует его определению как vector<vector<long int>>. Это не кажется возможным. Несмотря на то, что tempNs модифицируется функцией findPartition, он все равно должен оставаться вектором длинных целых чисел. Что мне не хватает?

используйте комментарии в коде, а не * перед кодом, так как * имеет какое-то значение в C++

Arkady Godlin 11.04.2018 12:17

Не в виде, а в. У вас может быть сумка, в которой есть другие сумки.

StoryTeller - Unslander Monica 11.04.2018 12:18
tempNs - это не то же самое, что nVals. Элементы nVals являются копиями tempN.
molbdnilo 11.04.2018 12:36

vector<vector<long> > имеет элементы типа vector<long>. Метод push_back() вектора копирует элемент в вектор. par.nValues относится к типу vector<vector<long> >, поэтому продвижение tempNS - типа vector<long> - вполне уместно.

Peter 11.04.2018 12:36
vector<vector<long int> > nVals; <- это определенный для приема векторов. Код помещает в него векторы с помощью nVals.push_back(tempN). tempN - это вектор.
Galik 11.04.2018 12:37

Спасибо за ответы, теперь это имеет смысл. Для подтверждения: предположим, что tempNs [5] = 2, и это третий вектор, который хранится в nVals. Означает ли это, что nVals [3] [5] = 2?

Allure 11.04.2018 12:54

Нет, значит nVals[2][5] = 2. Первый элемент вектора имеет нулевой индекс, а не единицу.

Peter 11.04.2018 13:03

@Peter предлагает написать это как ответ, так как он решает мой вопрос =)

Allure 11.04.2018 13:08
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
8
86
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Нет проблем с использованием вектора длинных векторов. Это почти то же самое, что и использование двумерного массива, но вам не нужно знать размер во время компиляции или управлять выделением памяти.

Скомпилировать этот код нетрудно. Элементы вектора могут быть примитивами (int, float, double), указателями или другими объектами (например, вектором или вашими пользовательскими классами).

Ограничения на (первый) параметр типа std::vector довольно слабые. Практически любой нереференсный тип может быть сохранен в std::vector, включая std::vector чего-то еще. Именно это и делает этот код.

Вы можете обернуть std::vector<long int> в

struct partition { 
    std::vector<long int> indexes; 
    double lambda; 
    double alpha; 
}; 

и замените potentialPars на

struct potentialPartitions {
    int nMaximum;
    int fNum;
    std::vector<partition> partitions;
};

что добавит ясности, но изменит способ доступа потребителя potentialPartitions к этим значениям.

Ответ принят как подходящий

vector<vector<long> > имеет элементы типа vector<long>.

Метод vectors push_back() копирует элемент в вектор.

В коде, который вы показали, par.nValues относится к типу vector<vector<long> >, поэтому продвижение tempNS, имеющего тип vector<long>, вполне уместно.

Другие вопросы по теме