foerever
foerever

Reputation: 335

Any way to maintain a struct array of references to an object? (C++)

I have a matrix that I want to be able to share access to via a struct array containing references to said matrix.

Is there any way to achieve this so I can modify the matrix by pulling from this buffer?

struct something {
    vector<vector<double>> &a;
};

something buffer[3];

void modify(something &arr) {
    (arr.a)[0][0] = 10;
    cout << (arr.a)[0][0] << endl;
}

int main(int argc, const char * argv[]) {
    vector<vector<double>> a(5, vector<double>(5));
    buffer[0] = {a};
    modify(buffer[0]);
    // want this to print 10
    cout << a[0][0] << endl;
    return 0; 
}

The problem with this, of course, is that a struct with a reference inside of it does not have a default constructor and thus can't be initialized in this way.

Upvotes: 0

Views: 52

Answers (3)

eerorika
eerorika

Reputation: 238361

You need to create the matrices first so that you can refer to them. That way you can initialise the references correctly:

vector<vector<double>> matrices[3];
something buffer[]{matrices[0], matrices[1], matrices[2]};

That is not the only problem however. Another is that you attempt to assign something:

buffer[0] = {a};

This is not allowed because something is not assignable. It is not assignable because the class contains a reference member.

// want this to print 10

There is no way to make the global reference refer to a local variable.

Given that you are trying to use the class in several ways that are contradictory to having a reference member, perhaps it would be better to re-design it to not use a reference.

This seems like a potentially good use case for a pointer. Unlike references, pointers can be assigned after initialisation. Be very careful however when storing pointers to local objects in the global array. It is very easy to end up with an invalid pointer.

Upvotes: 1

Azam Bham
Azam Bham

Reputation: 1399

This is a good use case for pointers, as they can be default constructed and you can assign different variables to them, unlike references:

struct something {
    vector<vector<double>> *a = nullptr; //pointer variable
};

something buffer[3];

void modify(something &arr) {
    //include nullptr check to prevent segmentation error
    if(!arr.a) return;
    //dereference arr.a to access it
    (*(arr.a))[0][0] = 10; 
    cout << (*(arr.a))[0][0] << endl; //dereference arr.a to access it
}

int main(int argc, const char * argv[]) {
    vector<vector<double>> a(5, vector<double>(5));
    buffer[0] = {&a};
    modify(buffer[0]);
    // want this to print 10
    cout << a[0][0] << endl;
    return 0; 
}

Be careful to track the lifetime of the objects pointed to by the pointers, as if they go out of scope before the pointers do, the pointers will become dangling.

Upvotes: 1

Joald
Joald

Reputation: 1134

It's best to think of a reference as not an actual object, but an abstraction for "a way to access the object". Since it's not concrete data, it cannot be put into containers. Your best bet for achieving a similar effect is to create an array of pointers. Depending on your C++ standard and memory allocation needs you will need to choose between raw or C++11's smart pointers (from the <memory> header).

Upvotes: 1

Related Questions