views:

115

answers:

6

Hello folks,

I have a vector< vector< vector< int>>> and I would like to extract from it a vector< vector< int>> to process it individually.

The problem is that when I write :

myMatrix = myCube[anIndex];

the matrix is copied but I only want a reference in order to save memory. Can you please help me out ?

Thanks a lot!

+1  A: 

Use an Iterator of type vector< vector< int> >::const_iterator. Hope this helps.

yesraaj
+1  A: 

vector::operator[] returns a reference - as long as you store that result into a reference instead of a full-blown object you should avoid a copy.

vector< vector<int > >& myMatrix = myCube[anIndex];
Michael Burr
+2  A: 

Just use

vector<vector<int> >& myMatrix = myCube[anIndex]; 
Jasmeet
Thank you for your (very quick :) ) answers. But in my case, myMatrix is actually an class member so if it is a reference, it must be initialized in the constructor.
Archanimus
@Archanimus: that should be no problem as long as the class that `myMatrix` is an instance of has an overload that takes an appropriate reference.
Michael Burr
@Archanimus: What is it currently initialized to in the constructor? You can use a `[]` expression (e.g. `myCube[anIndex]`) in the initializer list of the constructor. Whatever you do, references cannot be rebound, though.
Charles Bailey
@Archanimus, that's correct. But you need to use initializer list.
Jasmeet
well, I declare inside the class myMatrix as a reference to a vector-vector and I initialize it this way MyClass() : myMatrix() { }When I try then : myMatrix = myCube[anIndex] I got this message :Program received signal: “EXC_BAD_ACCESS”.???ps : sorry for the format, I don't know yet how to declare a portion of text as code... -_-"
Archanimus
Right, thats because references cannot be rebound (i.e. they can only be bound at initialization and that binding never changed after). See http://www.parashift.com/c++-faq-lite/references.html#faq-8.5
Jasmeet
A: 

If myMatrix is a class member and you want to be able to initialise it outside the constructor, your only choice is using a pointer:

class Whatever
{
  //...
  vector<vector<int>>* myMatrix;
  //...
}

  myMatrix = &myCube[anIndex]

EDIT: If you can live with initialising myMatrix in the constructor, you can use a reference:

class Whatever
{
  //...
  vector<vector<int> >& myMatrix;
  //...
}

Whatever::Whatever(vector<vector<vector<int> > >& myCube), int anIndex)
: myMatrix(myCube[anIndex])
{
  //...
}

Incidentally, you have to separate the > in your code, unless you are using a C++0x conformant compiler; otherwise, the compiler will parse the >> as operator>> and give you an error.

Gorpik
That's a solution but causes a problem of maintainability, I already have a lot of code referencing myMatrix. Actually, I thought that only a reference was copied until a find out that the memory usage was huge!
Archanimus
@Archanimus: Well, you cannot store a reference in a non-reference, non-pointer variable. Using a reference would force you to initialise it in the initialisation list of your class constructor and nowhere else; if you can live with that, then use a reference. I will update my answer to reflect it.
Gorpik
A: 

Instead of using operator[] use functions returning iterators as advance, and declare the matrix as follows

vector< vector< int> >::iterator myMatrixPtr;

myMatrixPtr = std::advance(myCube, anIndex);

Now you are able to work with myMatrixPtr as if it were a pointer. If you prefer a reference you can initialize one after this initialization

vector< vector<int > >& myMatrix = *myMatrixPtr;
Vicente Botet Escriba
A: 

Be careful with member references! If the referred-to object is cleaned up before the instance of MyClass is, you will have an invalid reference. Often (but not always), if you find that you need to use a member reference, it is an early warning sign that your design could be improved. I rarely use member references for anything other than as a handle to an object's owner, where I can be absolutely certain that the referred-to object will outlive the reference.

It might help if you change slightly your class' responsibilities. Right now, you are building up a set of data, and then creating an object to which you pass that set of data. Instead, why not first build the object, then put the data directly into it.

// To start, define your class to allow you to build up the data
class MyMatrix
{
public:
  MyMatrix ()
    { }

  void  setData (int x, int y, int data)
    { this->myData [x][y] = data; }
  int   getData (int x, int y)
    { return this->myData [x][y]; }

private:
  vector<vector<int> > myData; 
} 

// Then, create a vector of 6 (or however many you need) matrices
int numberOfMatrices = 6;
vector<MyMatrix> myCube (numberOfMatrices);

// Then, fill in the vector
for (int matrixIndex = 0; matrixIndex < numberOfMatrices; matrixIndex++)
  {
  // Fill in the data for this matrix
  MyMatrix &currentMatrix = myCube [matrixIndex];

  currentMatrix.setData (0 /* x */, 0 /* y */, 0 /* data */);
  // ... rest of data
  }

Then, you have all the data already in your objects, ready to be processed as you need. Plus, each object owns its data, so as long as the object is around, its member data will be valid. Best of all, using objects with usefully named member functions will make your code much more self-documenting than tons of nested containers.

Johntonsoup
Thank you very much for all your explanations ! Actually, I completely agree with you and, fortunately, in my case, i'm pretty sure that the data will not be lost. My design was motivated by decoupling my classes, cause' the source of date can be different things.
Archanimus