Reputation: 115
I have the following code that appends a part of a vector to another.
#include <algorithm> // std::copy
#include <iostream>
#include <vector>
#include <cmath>
#include <assert.h>
using namespace std;
void copyVec(const std::vector<double> in, std::vector<double> &out, int start, unsigned int length) {
assert(start>=0 && in.size()>=start+length);
out.reserve(length);
cout << in.at(9) << endl;
out.insert(out.end(), &in.at(start), &in.at(start+length));
}
int main(int argc, char ** argv) {
int start = 0;
int end = 9;
int window_size = 10;
// initialize
vector<double> vec1 = vector<double>(window_size);
for (unsigned int i=0;i<window_size;++i) vec1[i] = i;
vector<double> vec2 = vector<double>(window_size);
for (unsigned int i=0;i<window_size;++i) vec2[i] = i*10;
// print
cout << "vec1: ";
for (unsigned int i=0;i<vec1.size();++i) cout << vec1[i] << " "; cout << endl;
cout << "vec2: ";
for (unsigned int i=0;i<vec2.size();++i) cout << vec2[i] << " "; cout << endl;
copyVec(vec1,vec2,start,end);
// print
cout << "vec2: "; for (unsigned int i=0;i<vec2.size();++i) cout << vec2[i] << " "; cout << endl;
return 0;
}
I cannot seem to be able to access vec2's last element by reference. The output for this example (int end = 9) is
size: 10 start: 0 end: 9
vec1: 0 1 2 3 4 5 6 7 8 9
vec2: 0 10 20 30 40 50 60 70 80 90
in[9]: 9 &in[9]: 0x186d118
vec2: 0 10 20 30 40 50 60 70 80 90 0 1 2 3 4 5 6 7 8
and, of course, for int end = 10 I get an out of range error:
size: 10 start: 0 end: 10
vec1: 0 1 2 3 4 5 6 7 8 9
vec2: 0 10 20 30 40 50 60 70 80 90
in[9]: 9 &in[9]: 0xae1118
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check
Aborted (core dumped)
So how should I (efficiently) append the last vector element?
Upvotes: 0
Views: 175
Reputation: 311068
The correct function will look like
#include <iterator>
#include <vector>
//...
void copyVec( const std::vector<double> &in,
std::vector<double> &out,
std::vector<double>::size_type start,
std::vector<double>::size_type length )
{
assert( in.size() >= start + length );
out.reserve( out.size() + length );
out.insert( out.end(), std::next( in.begin(), start ),
std::next( in.begin(), start + length ) );
}
The first parameter is declared as constant reference. You should reserve memory for the destination vector taking into account its current size.
It is better to use own iterators of the vector instead of the raw pointers.
start
and start + length
specify a range like [start, start + length )
For example to copy the entire vector you can write
copyVec2b(vec1, vec2, 0, vec1.size() );
In general you may not write in the function like
cout << in.at( start + length ) << endl;
because index start + length
is not included in the range of copied elements.
You may write
if ( length != 0 ) cout << in.at( start + length - 1 ) << endl;
Upvotes: 1
Reputation: 217900
Your insert should use iterator directly:
out.insert(out.end(), in.begin() + start, in.begin() + (start + length));
Upvotes: 2