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!
Just use
vector<vector<int> >& myMatrix = myCube[anIndex];
Use an Iterator of type vector< vector< int> >::const_iterator. Hope this helps.
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];
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.
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;
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 ¤tMatrix = 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.
Related
I am not sure how to exactly express my thoughts and hence my googling is failing but is there a way to create const objects from non-const objects?
For instance, my graph class is as follows:
class graph
{
public:
graph( int n )
{
adj_list.resize( n );
adj_mat_wgt.resize( n, std::vector<double>( n ,100.0 ) );
_n = n;
};
~graph() {};
void add_arc( int u, int v, double wit );
std::vector<int> get_shortest_path( int source, int sink );
void set_const_gs_weights();
private:
std::vector<std::vector<int>> adj_list;
std::vector<std::vector<double>> adj_mat_wgt;
int _n;
};
}
I want to create another private variable and use set_const_gs_weights to create a copy of adj_mat_wgt but has some constness such that it can never be changed. The reason for this is that I will be modifying adj_mat_wgt though some functions and I need to go back to the original adj_mat_wgt by taking a non-const copy of the const object that I would like to create.
I understand that I can always just create another non-const variable like adj_mat_wgt_cpy and store a copy of adj_mat_wgt in it and never touch it except for using it to create another fresh copy for adj_mat_wgt after my changes. But is there a way to make adj_mat_wgt_cpy const? Any help is appreciated.
What's the best course of action in C++ to take in the following situation?
My class has some double pointer as a private member:
class A
{
private:
int** data;
//...//
public:
int** get_data () const { return data; };
//...//
}
And sometimes I'd like to check the values inside this pointer and change them. And there's some get function get_data for this purpose:
A* obj = new A();
//...//
int** data_from_A = obj->get_data();
// some manipulations with data_from_A pointer
But what if I want to be confident that nothing won't change it in the further usage?
How is it better to get only the "read access" to the data pointer?
Of course, we can make the data pointer public, but in this case it can be changed from the outside, that is unacceptable...
Thanks!
In C++, raw pointers, and especially pointer arithmetics, should only be used buried deep deep within a class that utilizes them for high performance computing.
The only reason to give something like a pointer to an array to the outside is that you use some other code that would be tedious to rewrite, like a highly optimized solver written by somebody who is used to writing C style code (with the solver actually being in C maybe).
If not, go with a class from the standard library, like std::vector (dynamic), std::array (static) or std::list (linked).
This would transform your code to something like
private:
vector<vector<int> > data;
public:
const vector<vector<int> >& get_data() const { return data; }
Simple as that, one const totally suffices, none more required for sub-vectors as it would be with a raw array.
Another way would be to go with
const int& get_data(const size_t i, const size_t j) const { return data[i][j]; }
which would work even with your current code.
For the vector, remember that if you want to use it for a while, then you have to get it with
const vector<vector<int> >& data = myClass.get_data();
and not with either of those
vector<vector<int> >& data = myClass.get_data(); //compile error
vector<vector<int> > data = myClass.get_data(); //works but unnecessarily copies the data
The answer is to make "data" private and make the function which sets it up a "friend". Then the member is protected from access, except within your special function.
However friend functions are usually a sign of poor design, so you will probably want to look at refactoring to eliminate the need for this.
I'm wondering how to get the maximum data locality and performance for the following problem without data copy.
I've a std::vector< MyClass* > where MyClass is something like
class MyClass
{
public:
MyClass(int n,double px,double py,double pz)
{
someField=n;
x=px;
y=py;
z=pz;
anotherField=100;
anotherUnusefulField=-10.0;
}
int someField;
int anotherField;
double x;
double y;
double z;
double anotherUnusefulField;
};
std::vector<MyClass*> myClassVector;
// add some values and set x,y,z
for (std::vector<MyClass*>::iterator iter = myClassVector.begin(); iter!=myClassVector.end();++iter)
{
MyClass *tmp = *iter;
tmp->x+=1.0;
tmp->y+=2.0;
tmp->z+=3.0;
}
I'm iterating frequently on these data and I also would like to enforce data locality. The data contained in the pointer to MyClass should be sent to a OpenGL vertex array, where the vertices are ONLY determined by x,y,z variables. As you may imagine is difficult to correctly set the strides, so I'm here to ask if there are other (portable) solution to this problem.
(p.s. I've already read the post VBOs with std::vector but my case is basically different because I have pointers and I also have other variables inside the class.)
I have pointers
Those pointers are useless to OpenGL, as they're in client address space. Also OpenGL doesn't dereference second level pointers.
and I also have other variables inside the class.
Well, then don't do this. If you passed those class instances to OpenGL you'd copy a lot of useless data. I recommend you just store a index into a tightly packed std::vector or array in your class members, and a reference to the vector/array itself. You can use getter/setter/referencer member functions to abstract away the access to the vector, i.e.
class …
{
// …
std::vector<v_t> *v;
size_t index_v;
x_t getX() const { return (*v)[index_v]; }
x_t setX(x_t x) { return (*v)[index_v] = x;}
x_t &x() { return (*v)[index_v]; }
};
In C++, I want to have a function that takes an optional argument of type vector. If the argument is not provided, I want the variable to have size 0. I currently have
void v_connect::import(vector<int> vid_,vector<double> vpos_,vector<int> vbd_,vector<int> bd_ss_=std::vector<int>() )
But this doesn't work. Basically, if the user provides the optional argument bd_ss_ I want to do a check bd_ss_.size()!=0 and then do some extra stuff. If the user does not provide the argument, I want bd_ss.size()==0. Is this possible?
There is no way to tell whether or not an optional argument is user-provided. However, you could use an overload:
void v_connect::import(
std::vector<int> vid_,
std::vector<double> vpos_,
std::vector<int> vbd_,
std::vector<int> bd_ss_)
{
check(!bd_ss_.empty());
do_extra_stuff();
do_import(vid_, cpos_, vbd_, bd_ss_);
}
void v_connect::import(
std::vector<int> vid_,
std::vector<double> vpos_,
std::vector<int> vbd_)
{
do_import(vid_, cpos_, vbd_, std::vector<int>());
}
// private:
void v_connect::do_import(
std::vector<int> vid_,
std::vector<double> vpos_,
std::vector<int> vbd_,
std::vector<int> bd_ss_)
{
// common import code goes here
}
You could make the user pass a pointer instead:
void foo(std::vector<int> * ov = NULL)
{
std::vector<int> dummy;
std::vector<int> & bd_ss_ = ov ? *ov : dummy;
if (ov) assert(!bd_ss_.empty());
// ...
}
Alternatively, use Boost.optional, which is a clever C++-style wrapper around this idea and allows you to have the same behaviour with a seamless interface.
Optional parameters go in the header, not the cpp.
As an aside you're mixing vector and std::vector, use one or the other (prefer to stick to std::vector).
I have some data class which is expensive to copy, but must be mutable, as it is frequently updated according to events. I also need a multi-index container to hold many such classes. I'm trying to set it up using boost::multi_index. For example:
struct MutableAndExpensiveToCopy {
int some_value;
std::map<int, std::string> some_huge_map;
std::map<int, std::string> an_even_bigger_map;
}
struct CanBeMultiIndexed
{
// "Payload" - its fields will never be used as indices
MutableAndExpensiveToCopy data;
// Indexes
int id;
std::string label;
}
typedef multi_index_container<
CanBeMultiIndexed,
indexed_by<
ordered_unique<member<CanBeMultiIndexed, int, &CanBeMultiIndexed::id>>,
ordered_non_unique<member<CanBeMultiIndexed,std::string,&CanBeMultiIndexed::label>>
>
> MyDataContainer;
My problem is that multi_index treats elements in the container as constants (in order to keep the integrity of all of the indices). For example, the following won't compile:
void main() {
// put some data in the container
MyDataContainer container;
CanBeMultiIndexed e1(1, "one"); // conto'r not shown in class definition for brevity
CanBeMultiIndexed e2(2, "two");
container.insert(e1);
container.insert(e2);
// try to modify data
MyDataContainer::nth_index<1>::type::iterator iter = container.get<1>().find(1);
iter->data.some_value = 5; // constness violation
}
I cannot use the replace() method, as it is expensive to copy the payload class.
I'm aware of the modify() method, but using it seems cumbersome, since in my real program, the "payload" class may contain numerous fields, and writing a functor for each and every one it out of the question.
Any suggestions?
EDIT: After some playing around, I've tried replacing the data element with a shared_ptr to MutableAndExpensiveToCopy:
struct CanBeMultiIndexed
{
// "Payload" - its fields will never be used as indices
boost::shared_ptr<MutableAndExpensiveToCopy> data;
// Indexes
int id;
std::string label;
}
This worked, and I was able to compile my main() including the data-modifying code:
void main() {
...
iter->data->some_value = 5; // this works
...
}
This pretty much gives me what I wanted, but I'm not sure why this works, so:
Does this code does what I intended, or is there some caveat I'm missing?
How come this works? Does the constness of the shared_ptr does not apply to its -> operator?
First of all, ImMutableAndExpensiveToCopy seems precisely to be the opposite --mutable, since you're trying to change its contents in the example. Try simply this:
struct CanBeMultiIndexed
{
mutable ImMutableAndExpensiveToCopy data;
int id;
std::string label;
}
(and possibly change the name ImMutableAndExpensiveToCopy for consistency.)