Reputation: 589
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.
Upvotes: 0
Views: 733
Reputation: 26282
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 ofT
. No copies are made.
vector(size_type count, const T& value);
Constructs the container with
count
copies of elements with valuevalue
.
For T = unsigned int
, the "default-inserted instance" is just 0u
.
Upvotes: 4