HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Vector of vectors in contiguous memory

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
vectorsvectormemorycontiguous

Problem

I have a class Vector3d with 3 double components and want to store several of them in a Field. For reasons of efficiency when sending a Field over a network via MPI, I would like to allocate contiguous memory in the Field class and let the Vector3ds store their components in that chunk of memory. In addition, Vector3ds should also be able to live without a Field; in this case, they have to care about their own memory allocation.

#include 
#include 
#include 

class Field;

class Vector3d
{
    friend class Field;

    public:
        Vector3d() : components_(new double[3]) {}
        ~Vector3d() { delete[] components_; }
        Vector3d(const Vector3d &v) : components_(new double[3])
        {
            components_[0] = v.components_[0]; 
            components_[1] = v.components_[1]; 
            components_[2] = v.components_[2];
        }
        double & operator()(const std::size_t index) { return components_[index]; }

    private:
        Vector3d(double *ptr) : components_(ptr) {};
        double *components_;
};

class Field
{
    public:    
        Field(std::size_t size);
        ~Field();
        Vector3d & operator()(const std::size_t index) { return *(vectors_[index]); }

    private:
        std::vector components_;
        std::vector vectors_;
};

Field::Field(std::size_t size) : components_(std::vector(3 * size)), vectors_(std::vector(size, new Vector3d(0)))
{
    double *ptr = &components_[0];
    for (auto it = vectors_.begin(); it != vectors_.end(); ++it)
    {
        (*it)->components_ = ptr;
        ptr += 3;
    }
} 

Field::~Field()
{
    for (auto it = vectors_.begin(); it != vectors_.end(); ++it)
        (*it)->components_ = 0;
}

int main(int argc, char *argv[])
{
    Field field(2);
    Vector3d &v = field(1);
    v(2) = 5;

    Vector3d v2 = v;
    v2(2) = 2;

    std::cout << field(1)(2) << std::endl;

    return 0;
}


I would like to hear what you think about this piece of code. Can this be considered a goo

Solution

When it comes to multidimensional vectors I usually suggest two approaches.
  1. vector/array (C++11 and later)



This only works, when the inner dimensions are fixed and only the outer is runtime dynamic. In the end it comes down to something like this:

std::vector> field;


In your case a Vector3d would either derive from std::array or contain one.
  1. simple vector



This approach simply creates a one dimensional vector with X * Y size.
The element (x, y) can then be addressed with vec[y * X + x]. This works also with the older C++ standard. Although I think this solution might not work in your setup.
Bonus

I just want to highlight @Yakk's comment. Your Vector3d could look like this:

class Vector3d
{
public:
    // stuff
    // ...
private:
    double components_[3];
};


This way the memory would also be contigous.

Code Snippets

std::vector<std::array<T, N>> field;
class Vector3d
{
public:
    // stuff
    // ...
private:
    double components_[3];
};

Context

StackExchange Code Review Q#83912, answer score: 4

Revisions (0)

No revisions yet.