Ata3ias
Ata3ias

Reputation: 115

Get last vector element by reference

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

Answers (2)

Vlad from Moscow
Vlad from Moscow

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

Jarod42
Jarod42

Reputation: 217900

Your insert should use iterator directly:

out.insert(out.end(), in.begin() + start, in.begin() + (start + length));

Upvotes: 2

Related Questions