I have another suggestion for the OP. You seem to want to write some kind of
matlab program. And you seem to be concern about the speed of copying vectors. From this, I am making the following assumption about your later usage of vector. If they are wrong, then the rest of the text may hardly or not at all apply to your problem:
1) You are creating rather big vectors. Means not only like 3-elements (3D-Vector), but a vector with dozends of elements.
2) You are usually combining the vectors together, e.g. adding vectors to other vectors, scaling vectors by a scalar etc. instead of setting the elements directly all over the place.
If so, you could consider postponing the creation of the vector's values even more until you actually
read the values. Let me explain..
Usually you create a vector by using some default memory for each cell, right? In your original synopsis,
explicit vec(int n);
probably creates a vector of n elements, each of it beeing 0. But at this point, there is no real need to create a memory block all filled with 0. You could just remember "I have a vector of size n with all zeroes."
Then later you work with the vector. You may add two vectors together, using some "v3 = v1 + v2". But even here, it may be much faster and much less memory consuming, if you just remember "the resulting vector v3 is an addition of v1 and v2 vector" instead of every single value.
Only if you read out a single element, you have to calculate the value of said element. Even then, you don't have to allocate memory for that. You remembered the "chain of operations" for this vector, so you just execute this chain for the requested memory cell.
The downside is, that now each "single element write access" operation need to be stored as an additional chain link.
It will look along those lines
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
|
struct Operation { virtual ~Operation(){} virtual int execute(int index, int current) = 0; };
struct SetPos : Operation // for setting a specific position only
{
int constant, index;
SetPos(int c, int i):constant(c), index(i) {}
virtual int execute(int index, int current) { return i == index ? constant : current; }
};
struct Transpose : Operation // adding two vectors is called "transpose"
{
vec<int> v;
Transpose(const vec<int>& rhs):v(rhs){}
virtual int execute(int index, int current) { return current + v[index]; }
};
struct Scale : Operation // scaling by a scalar
{
int scale;
Scale(int s):scale(s){}
virtual int execute(int index, int current) { return current * scale; }
};
... // usually you'll end up in one operation per operator in your command line shell you have
struct vec
{
std::list<std::tr1::shared_ptr<Operation>> operations;
int size;
vec(int n) : size(n) {} // no memory allocation here!
vec(const vec& rhs) : operations(rhs.operations), size(rhs.size) {} // sharing operations
int operator[](int index) const // element read access
{
int v = 0; // initial value is 0
for (auto it = operations.begin(); it != operations.end(); ++it)
v = (*it)->execute(index, v);
return v;
}
};
vec operator+(vec lhs, const vec& rhs)
{
lhs.operations.push_back(std::tr1::shared_ptr<Operation>(new Transpose(rhs)));
return lhs;
}
| |
I only picture the idea for int's here and also was a bit sloppy with the interfaces (no private etc..). E.g. you should make sure your operation are immutable. (you only add operations and never change them).
Depending on the usage pattern of your vector class, this will decrease your memory consumption to a tiny fraction (if you have my 1) and 2) as typical operations) or just bloat up your PC (if you usually use for-loops to set every value step-by-step).
But especially for command line mathlab-similar tools where you don't set too many values anyway but usualy work with generated data, this technique can be skyrocking awesome. ;-)
Ciao, Imi.
PS: About your original question "how to not return a full copy": As Disch said, better forget about it. ;) Scott Meyer has an excellent chapter about this in "Effective C++" (or "More Effective C++". Don't remember), and he is right. It's more pain than worth it.
PPS: Disch: you may to rethink line 48 of your code and where this->dat is (still) pointing. ;-)