0

In my learning process about C++, I am having hard time understanding the best practice for initializing a vector in this particular setting:

struct Data {
    vector<int> vec;

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

so that in the main function I just declare Data mydata(10); and mydata will have an attribute vector mydata.vec of k=10 elements.

However, I really find unefficient that one has to setup a for loop and fill mydata.vec element by element, so looking online I found other methods that honestly I did not understand. Anyway, I tried to replace that given constructor with

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

and

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

with either error messages about modified objects already deleted or segmentation faults happening during runtime. Would you please explain the most C++'ish or most efficient way to initialise a vector in such framework? Consider that for some reason I have little to no understanding about what an initialization list is.

EDIT: Here I propose a minimal example directly taken from my code:

#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;
}

I am sorry to not to do better in reducing further. This code produces a segmentation fault. However, commenting the HERE 2 line and using HERE 1 apparently saves the situation. I don't get why.

3

1 Answer 1

4

After the for loop

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

the count vector will contain 2k zeros. But after count.resize(k) it will contain only k zeros.


Fixed constructor might look like this:

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

To assign sequentially increasing sequence to mydata, you can use std::iota algorithm. , 0 can be dropped without changing the behaviour, but you might want to be explicit about the initial value.

Semantics of these two constructors is very simple:

explicit vector(size_type count);

Constructs the container with count default-inserted instances of T. No copies are made.

vector(size_type count, const T& value);

Constructs the container with count copies of elements with value value.

For T = unsigned int, the "default-inserted instance" is just 0u.

Sign up to request clarification or add additional context in comments.

1 Comment

Ok, I guess this is basically what I was looking for. Thank you so much.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.