I'm making custom vector and matrix class for numerical calculations.
I want to treat each row and column of the matrix as a vector. Also, I do not want to use extra memory, therefore, I made VectorView class which uses data in matrix directly(Like GSL library). Here is the outline of my matrix class.
class Matrix{
priavte:
T data[];
....
public:
VectorView row(int n);
VectorView colum(int n);
};
And I define a function which uses VectorView.
myFunc(VectorView& v);
My VectorView class has some extra data, therefore I want to use VectorView as a reference to save memory.
However, I got a problem when I calling a function like this.
Matrix m;
...
...
myFunc(m.row(i));
The problem is that m.row(i) returns temporary object therefore I cannot use reference type to treat it. But
auto v = m.row(i);
myFunc(v);
this does not makes a error even though it is exactly same but not clear reason to use v. I want to use the above one. Is there an brilliant solution for this type of problem?
row returns an rvalue reference (VectorView&&), which cannot be passed as a non-const lvalue reference (VectorView&). You can either redefine myFunc as myFunc(const VectorView& v) or myFunc(VectorView&& v), depending on your requirements and the behaviour of VectorView.
If myFunc needs access to non-const members of VectorView, you'll need to define the latter, which will pass the returned value from row into myFunc using move semantics. However, since VectorView is just a "view" onto the original data, it possibly doesn't have (or need) any non-const members, in which case, you should use the former.
use valarray and gslice
http://www.cplusplus.com/reference/valarray/gslice/
N-D (including 2D) matrices are why Bjarne added gslices (AFAIK)
Don't reinvent the wheel and use Eigen
eigen.tuxfamily.org
is a header-only c++ matrix library with very good support and performance
Guess your vector view contains only a pointer to original data and a integer for step (1 for row, n for column). In that case treat it as a value object is fine (as long as you make sure the life cycle of matrix is good). So if you want the syntax, you can just use value in myFunc. Like: myFunc(VectorView) ...
Write two VectorViews: VectorView and ConstVectorView. The first holds a view of a slice of data, and a method is const iff it does not change which slice you are looking at. Changing members is ok in a const method of VectorView.
ConstVectorView is a view of a vector where changing the value of elements is illegal. You can change what you are viewing with non-const methods, and you can access elements to read with const methods.
You should be able to construct a ConstVectorView from a VectorView.
Then, when you return a VectorViewand pass it to a function, the function should either take it by value, or take it by const&. If the function doesn't modify its contents, it takes a ConstVectorView.
Make your life simple, and stick to C-style semantics (this allows you to use the wealth of C linear algebra code available out there, and easy to use the fortran ones as well).
You state that you are concerned about using extra memory, but if you are simply concerned and do not have tight bounds, ensure you store the matrix in both row and column format. This will be crucial for getting any kind of performance out of common matrix operations (as you will be using whole cache lines at a time).
class Matrix{
private:
T rowData[];
T colData[];
...
public:
T const * row(int n) const;
T const * colum(int n) const;
...
};
Related
Is it bad practice to return a vector element by reference?
class X{
vector<Y> v;
public:
Y& getRefFromVectorOfY(unsigned int index){
retrun v.at(index);
}
void addToVectorOfY(Y y){
v.push_back(move(y));
}
};
While this is efficient and clean, the issue is that it breaks encapsulation. If v is a vector, and a private member of a class, the caller will now have a ref to an element in the private vector that they can not only read from but also assign to (overwrite).
Can do this
x.getRefFromVectorOfY(0).setNumber(7); //not bad..actually good
or
x.getRefFromVectorOfY(0) = move(Y2); //very bad!
or even
Y3 = move(x.getRefFromVectorOfY(0)); //OMG
Of course, we may return a const & instead, allowing only const operations.
Returning an element by value is less efficient since it is a copy.
If the get method was to move the element out of the vector to return by value, the vector would lose data integrity since it would no longer store the data that was moved out (element would be reset to default state inside the vector... so... still left in the vector but as junk data).
WHY AM I ASKING THIS? THE PERSPECTIVE
If you're following the rule of zero, and you have a private vector member in a class, you need convenience methods to axs and set the vector. This raises the question how to return values.
The problem with return by ref is that it breaks encapsulation unless it is const ref.
So, should I only return a const ref forcing any setting of values to use the setVector method? The problem with this is that sometimes you store custom type...like Y..in the vector and you need to access Y's non-const methods. While a const & protects the vector element from being re-set or overwritten in the vector, it also prevents caller from using the returned elements non-const methods.
So if I only return const &... I can't do
x.getRefFromVectorOfY(0).setNumber(7); //Y has a setNumber method
and that would be a problem. It would be a problem because I don't want to re-implement any of Y's methods in class X. That would be another layer of indirection and a lot of code redundancy. This speaks against having a return a const & general policy. Not practical in many cases.
So I would have to override based on constness of return value, which you can't do.
So I would have to have two get functions with diff names, one returning const &... and other just returning a &. That feels dirty.
const Y& getConstRefFromVectorOfY(unsigned int index){
retrun v.at(index);
}
Y& getRefFromVectorOfY(unsigned int index){
retrun v.at(index);
}
EDIT
I added this table to summarize the issues and the goals.
I want the caller of class X be able to do the following safely and efficiently:
MOD VECTOR
MOD ELEMENT IN VECTOR
READ ELEMENT IN VECTOR
Summery of options as I understand them:
"-" is a con and "+" is a pro.
OPTION 1 -- Return copy of vector element
MOD VECTOR
+ Can mod vector via class method addToVectorOfY
MOD ELEMENT IN VECTOR
- No way to mod Y element itself in vector without
indirection & redundancy (re-implementation of some Y methods)!!!
Because modifying returned copy does not modify what is in vector.
READ ELEMENT IN VECTOR
+ Yes, inefficiently can read element data by looking at copy of element
OPTION 2 -- Return ref of vector element
MOD VECTOR
- Can mod vector in non-obious ways via returned ref to element. Breaks encapsulation.
Dangerous and also redundant because class has setter method to mod vector.
+ Can mod vector via class method addToVectorOfY
MOD ELEMENT IN VECTOR
+ Can call non-const methods of element returned
- Some danger to the reference being invalid upon vector resize
READ ELEMENT IN VECTOR
+ Yes, with maximum efficiency
- Some danger to the reference being invalid upon vector resize
OPTION 3 -- Return const ref of vector element
MOD VECTOR
+ Can mod vector via class method addToVectorOfY
MOD ELEMENT IN VECTOR
- No way to mod Y element itself in vector without
indirection & redundancy (re-implementation of some Y methods)!!!
READ ELEMENT IN VECTOR
+ Yes, with maximum efficiency
- Some danger to the reference being invalid upon vector resize
Is there a way for a user of class X to do all 3 safely and efficiently?
Well, std::vector's own operator[] returns a non-const reference, so it's not bad practice in itself. Specifically, this doesn't "break encapsulation" - a vector is not supposed to encapsulate away its members, it's supposed to provide access to them.
Also, all of your 3 examples are fine, not just the first one. It's not "very bad" nor "OMG".
Having said that, remember that an std::vector's storage gets re-allocated as its size changes (at least - during size increases), so it doesn't guarantee the validity of pointers/references into it.
So what's bad is to keep references (and pointers, and opaque iterators) into an std::vector around when it might get resized.
Is it bad practice to return a vector element by reference?
Yes, in general? In most cases, I would think if you took the time to encapsulate a member variable of a class as private in order to control the access and manipulation of that variable, designing a member function that will easily break that control renders the first step moot. This may not always be true depending on the use case, but here you pose the problem so abstractly that it is hard to give a specific answer. The only real problem I can identify in your post is this:
Returning an element by value is less efficient and since it is a copy, it is less efficient.
I guess the real question to ask here is there a meaningful, measurable performance difference between maintaining greater access control to the member variable versus having more direct access to the underlying memory so you can manipulate it faster? You are right that the return by reference is more efficient in some ways, but does that actually make a practical difference in your particular code?
Additionally, it also matters what level of data integrity you need to maintain for the private member variables you are exposing. einpoklum makes a great point that many standard containers follow this paradigm. They have no expectations on the values that are stored in the container, only that they maintain control over allocation/deletion of the memory held by them. Your class may have a stronger control requirements about what values the member values take. For example, if all the data elements in that vector needed to be non-negative, then by exposing a reference to that memory you lose the ability to have the class make those kind of data integrity guarantees. It really just depends on the requirements, although I prefer the paradigm of selectively releasing control over a member variable as needed rather than giving full access and slowly taking it away when you want to add additional guarantees.
I would like to do something like this in c++ (but I cant since there is no "baseobject" like in for example JAVA)
double integrate(double(*integrand)(InputData, int), vector<BaseObject>& inputdata){
...
for(...)
value+= integrand(inputdata, someIntVariable);
...
return value;
}
where I have put different types of objects in inputData that shuold be input for my integrand-function. I then can just cast these values inside my integrand-functions
double integrand1(vector<BaseObject> &inputdata, int s){
double d = (double) inputdata.at(1);
char s = (char ) inputdata.at(2);
... do stuff with d ans s
}
How can I accomplish this in some other way?
Edit I understand why it is not a good idee to pass a vector by value, I just wanted to show that I need a collection of different data for different integrands.
I can explain what my goal with the function is: I want to do a general integration-function, so I can can pass a general "integrand" that my function then integrates numerically. However, different integrands needs completely different input data (say maybe some need 4x4 matrices etc).
In java anything more complex than an int is a reference. In C++ objects are not references by default. This makes it impossible to store different objects in a vector since each object type will require a different ammount of space to store it (vectors store objects contiguously).
To achive what you want you will have to use pointers (a more generalized version of a reference since you can perform pointer maths on a pointer). There is nothing wrong with using a vector of void* but you are probably better off using a common base class for all the objects you want to store in the vector since you will need some way to find out the type before you can process your objects (C++ has very limited RTTI).
Use boost::any.
vector<boost::any> inputdata
The C++ way to do this is with templates:
template<typename integrand_type, typename inputdata_type>
double integrate(integrand_type &&integrand, const inputdata_type &inputdata){
...
for(...)
value+= integrand(inputdata, someIntVariable);
...
return value;
}
... assuming inputdata should be a constant container of some sorts. Also, you do understand that passing a vector by value, as a function parameter, makes a complete copy of the vector, right? That's why you need a reference.
Java objects are completely different from C++ objects. In Java, when you reference an object you are really referencing a pointer to an object. All objects in Java are references. In C++ you have to be explicit as to what you want, otherwise you will end up producing terribly inefficient code.
I'm working on some code in which a variable of type std::vector<double> is declared, before the value is specified. I can't define the value together with declaration, because it takes many lines of code to set the value. The thing is that this variable is a constant in essence, meaning it shouldn't be modified once it's set. However, it can't be declared const.
One way is to create another variable which is const and copy the value into it. const std::vector<double> a(b); would do, and use a instead of b in the program. However, my variable can be large and I wish to learn a way other than having to perform copying.
Any suggestions from you guys?
You may create a function to initialize it. In worst, you have a move. at best you have (N)RVO (return value optimization).
std::vector<Object> CreateBigVector();
And then
const std::vector<Object> myObject = CreateBigVector();
One way is to create a function
std::vector<Object> CreateYourVector();
and use it to initialise
const std::vector<Object> vec = CreateYourVector();
Another (technically a variation) is to create a helper class that contains your vector, and do all the work in a constructor
class Helper
{
std::vector<Object> vec;
public:
Helper()
{
// initialise your vector here
};
const std::vector<Object> &TheVec() const {return vec;};
};
const Helper helper;
The above techniques can be combined, for example change the constructor
Helper() : vec(CreateYourVector()) {};
These techniques can also be mixed with others, such as the singleton pattern.
I think the problem is about scoping. You have to separate your problem into two different scopes:
a scope where you build up your vector
a (or others) scope(s) where you use it
In the scope where you build up your vector, it logically isn't a const variable. Once you have built it, you want it not to be changed anymore. So you may want to refer to it through a const &.
I'd go this way:
define a function std::vector<double> build_up()
inside build_up, you define a non-const vector and you can build it
when you're done, you can return it by value (RVO will avoid any copy)
refer to the object returned by build_up() as a const object
I.e.
const std::vector<double> v = build_up();
In c++11, you can use the initial list to define a const vector. I think it is a easiest way. Try it: const vector<double> = {1.0, 2.0, 3.0};. It will not take many lines of code to set the value. I hope this can help you.
The traditional approach would be to only expose a handle that enforces constness and avoids making expensive copies outside the context where the vector is created and initialized. Such handle would be a const pointer or reference.
Since you are using std::vector you can benefit from modern c++ facilities, since std::vector supports features like move semantics off-the-shelf.
In particular, I suggest you to budget some time to have a look at:
move semantics
smart pointers
which upgrade the traditional way of passing around raw pointers. They enforce ownership semantics (which context owns the object) and allow you to express your intentions in a very precise way through the code.
I need to sort a vector of custom type std::vector<Blah> v by Blah's integer id. I do this via std::sort(v.begin(), v.end()) with the operator < being overloaded within Blah as
bool operator< (const Blah& b) const { return (id < b.id); }
I noticed that Blah's private id cannot be declared as const int id, otherwise the type Blah does not meet the requirements for std::sort (I assume it conflicts with not being ValueSwappable?)
If id is not const everything is fine. However, I dislike the idea of the objects not having constant ids just for the requirement of rearranging their order within a vector.
Is there a way around or is this the way it is?
Is there a way around or is this the way it is?
I fear that this is the way it is. If you want to sort a vector, which is in principle an array, then you have to assign to elements when exchanging them.
At least that is what i thought, actually you can cheat a bit. Wrap your objects into an union:
template<typename T>
union ac {
// actual object
T thing;
// assignment first destructs object, then copy
// constructs a new inplace.
ac & operator=(ac<T> const & other) {
thing. ~T();
new (& thing) T(other. thing);
}
// need to provide constructor, destructor, etc.
ac(T && t) : thing (std:: forward<T>(t))
{}
ac(ac<T> const & other) : thing (other. thing) {}
~ac() {
thing. ~T();
}
// if you need them, add move assignment and constructor
};
You can then implement the (copy) assignment operator to first destruct the current object and then (copy) construct a new object from the provided inplace of the old object.
You also need to provide constructors and destructors, and of course this only works with C++11 and beyond due to limitations concerning the union members in previous language standards.
This seems to work quite nice: Live demo.
But still, I think you should first revisit some design choices, e.g. if the constant id really needs to be part of your objects
Is there a way around or is this the way it is?
So you want to update / swap the entire data of an object (including it's identity) and to keep the identity constant; the two are in conflict, because constant means "doesn't change" (and swap means "change these instances").
You have stumbled here on the two (competing) definitions of const-ness: conceptual const-ness (what the data says/means is the same) and binary const-ness (the bytes representing the data do not change). (The first definition is what lead to the introduction of mutable in the language: the ability to keep conceptual constness while breaking binary const-ness).
Your data here is conceptually constant (the interface to the data should be const) but not binary constant (you can swap values, so your bits may go away to another instance).
The canonical idea for this is to keep the data non-const internally, and provide only const public/protected access for client code.
You say:
However, I dislike the idea of the objects not having constant ids just for the requirement of rearranging their order within a vector.
Just because the identity is conceptually constant (exposed API is/should be constant), you have no actual hard requirement to keep the data constant (and should have no preference towards it, based on the API).
As part of a couple larger projects I’m working on developing a matrix template class which dynamically allocates blocks only when a value for an element in a block is altered from a defined initializer value. This class is going to be used in some fairly complex math so I’m trying to keep the interface as simple and intuitive as possible. I wanted to be able to use operator(row, col) to access matrix elements by reference instead of using get(row, col) and set(element) methods.
This became problematic however as due to the allocation behavior the actions for set and get need to be different and need to test the value being set against the initializer value. This can’t be done just returning a reference so I made a helper class which contains the reference and can be converted to the correct data type, and returned that. This is the structure of the interface:
template <class T>
class Container{
public:
// Element class which contains a reference to a data element
class Element{
public:
// Constructor -- Initialize the element reference
Element(T & element) : _element(element){}
// Assignment operator -- SET
Element & operator=(const T & that){
_element = that;
return *this;
}
// Element to element assignment -- GET that, SET this
Element & operator=(const Element & that){
this->_element = that._element;
return *this;
}
// Implicit conversion operator -- GET
operator T(){
return _element;
}
private :
T & _element; // Element reference
};
// Return an element class containing a reference to the element
Element operator()(int index){
return Element(_data[index]);;
}
private:
T _data[10];
};
It relies on implicit conversion to be able to use the returned Element class as if it were of type T. I tested it and it seems to work fine for basic assignment and arithmetic operations on base types but for operators such as incrementing and binary shifts the implicit conversion isn’t made and the operation results in a compiler error. And I’d assume I’d find a host of further issues trying to use it with T as a class structure, pointer, etc.
That, along with the fact that seems like very bad practice to rely on implicit conversion for the correction functioning of a class, makes me think I need to come up with another approach. Is there any way I can fix my current approach? Some other approach that I might take? Or should I just give up on this and make the operator(row, col) as always allocating with get and set methods allocating only when necessary?
There's only so much magic you can do for you.
I want to first point you to Blitz++ and Thrust as some good didactic examples. In the first case, those "magic references" are heavily used to access regions of the data through subarrays, among other things. The second case is used to safely access data from other memory spaces (such as in the GPU), dealing with data download/uploads automatically.
I would recommend focusing on the common usage; is your container being used mostly to hold scalar values? Then just provide the common arithmetic operations such as ++, +=, etc that forward to the actual implementations. You'll see that's the approach used in 2. The downside is it's a bit more inconvenient to access members of the internal data - but if that's an uncommon scenario, it would be a good trade-off.