C ++ - std :: vector инициализация в конструкторе - PullRequest
0 голосов
/ 18 января 2020

В моем процессе изучения C ++ мне трудно понять, как лучше инициализировать вектор в этом конкретном параметре:

struct Data {
    vector<int> vec;

    Data(const int k) {
        for (int i = 0; i < k; i++) vec.push_back(0);
    }
};

, поэтому в основной функции я просто объявляю Data mydata(10); и mydata будет иметь вектор атрибута mydata.vec из k=10 элементов.

Однако, я действительно считаю неэффективным, что нужно установить для l oop и заполнить mydata.vec элемент за элементом, поэтому Посмотрев онлайн, я нашел другие методы, которые, честно говоря, я не понял. В любом случае, я пытался заменить данный конструктор на

Data(const int k) {
    vec.resize(k);
}

и

Data(const int k) : vec(k,0) {}

сообщениями об ошибках уже измененных объектов или ошибками сегментации, возникающими во время выполнения. Не могли бы вы объяснить наиболее C ++ 'i sh или наиболее эффективный способ инициализации вектора в такой среде? Учтите, что по какой-то причине я почти ничего не понимаю о том, что такое список инициализации.

РЕДАКТИРОВАТЬ: Здесь я предлагаю минимальный пример, непосредственно взятый из моего кода:

#include <iostream>
#include <vector>

using namespace std;

struct Data {
    vector<unsigned int> mydata, count;

    Data(const unsigned int k) {
        for (unsigned int i = 0; i < 2 * k; i++) {
            mydata.push_back(i + 1);
            //count.push_back(0);  // HERE 1
        }
        count.resize(k); // HERE 2
    }

    void update_stats(const unsigned int p) { count[mydata[0] - 1] += 1; }
};

void twist(Data& stuff, const unsigned int m) {
    unsigned int temp;
    for (unsigned int i = m; i < 2 * m; i++) {
        temp = stuff.mydata[i];
        stuff.mydata.erase(stuff.mydata.begin() + i);
        stuff.mydata.insert(stuff.mydata.begin() + (i - m) * 2, temp);
    }
    stuff.update_stats(m);
}

int main() {
    unsigned int p, k = 200;
    Data stuff(k);

    for (p = 1; p <= k; p++) twist(stuff, p);
    for (p = k; p >= 1; p--) twist(stuff, p);

    cout << stuff.count[stuff.mydata[0] - 1] << endl;
    return 0;
}

Извините чтобы не делать лучше в дальнейшем сокращении. Этот код вызывает ошибку сегментации. Однако комментирование строки HERE 2 и использование HERE 1, по-видимому, спасают ситуацию. Я не понимаю, почему.

1 Ответ

4 голосов
/ 18 января 2020

После for l oop

for (unsigned int i = 0; i < 2 * k; i++)
    count.push_back(0);

вектор count будет содержать 2k нулей. Но после count.resize(k) он будет содержать только k нулей.


Фиксированный конструктор может выглядеть следующим образом:

Data(const unsigned int k) : mydata(2 * k), count(2 * k, 0) {
    std::iota(mydata.begin(), mydata.end(), 1u);
}

Чтобы назначить последовательно увеличивающуюся последовательность mydata, вы можно использовать алгоритм std::iota. , 0 можно отбросить, не меняя поведения, но вы можете явно указать начальное значение.

Семантика этих двух конструкторов очень проста:

explicit vector(size_type count);

Создает контейнер с count вставленными по умолчанию экземплярами T. Копии не создаются.

vector(size_type count, const T& value);

Создает контейнер с count копиями элементов со значением value.

Для T = unsigned int, «вставленный по умолчанию экземпляр» просто 0u.

...