简体   繁体   中英

Efficient subset of a std::vector<double>

Assume that we have set of double numbers in a std::vector<double> . Lets call this one data . Now I want to create a new std::vector that is made of an (ordered) subset of data via a method subvector , eg let data = [0,4,3,5,5,7] and I want method that gives me

std::vector<int> indices(3);
indices[0] = 1;
indices[1] = 2;
indices[2] = 4;
std::vector<double> subdata = data.subvector(indices);

and the result should be subdata = [4,3,5] . Of course, I can achieve this by simply copying out the values of data but what I really want is that if I change values in subdata , they also change in data , ie if I do subdata[2]=-1 is want that data = [0,4,3,5,-1,7] .

So, I have to do thing like "remembering" the pointer of in data . I tried several options with putting & and * here and there but I could not get the desired result.

Storing pointers to the items is a bit dangerous, because a vector's internal buffer can be replaced (automatically) when you append items, and then those pointers would be dangling.

But you can store a pointer or reference to the vector itself, like this:

#include <vector>
#include <initializer_list>
using namespace std;

class Subdata
{
    vector<int>&        m_data;
    const vector<int>   m_indices;

public:
    auto operator[]( const int i )
        -> int&
    { return m_data[m_indices[i]]; }

    Subdata( vector<int>&  data, const initializer_list<int>& indices ):
        m_data( data ),
        m_indices( indices.begin(), indices.end() )
    {}
};

#include <iostream>
auto main()
    -> int
{
    vector<int> data = {0, 4, 3, 5, 5, 7};
    Subdata subdata( data, {1, 2, 4} );
    subdata[2] = -1;
    for( const int v : data ) { cout << v << ' '; } cout << endl;
}

what I really want is that if I change values in subdata, they also change in data, ie if I do subdata[2]=-1 is want that data = [0,4,3,5,-1,7] .

To accomplish that, you need to store pointers to the members in data . They can be raw pointers ( int* ) or iterators ( std::vector<int>::iterator ).

However, storing pointers is risky. They can be invalidated by modifications to data . The safer method would be to just use the indices and get/set the values of the elements of data by using the indices.

data[indices[0]] = <some value>; // Set the value in data
int x = data[indices[1]];        // Get the value from data

Since std::vector is a random access container, the cost of accessing the elements of data will not impact performance, if that is a concern.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM