I have a vector as member in a class and I want to return a reference to it through a getVector() function, so as to be able to modify it later. Isn’t it better practice the function getVector() to be const? However I got an error “qualifiers dropped in binding reference of type…” in the following code. What should be modified?
class VectorHolder { public: VectorHolder(const std::vector<int>&); std::vector<int>& getVector() const; private: std::vector<int> myVector; }; std::vector<int> &VectorHolder::getVector() const { return myVector; }
vector<SalesItem> *getSalesItems(); returns a pointer and does not return a reference. void Invoice::getSalesItems() doesn't return anything. The function definition in the class and the declaration must be the same: vector<SalesItem> & getSalesItems(); returns a vector by refernece.
A C++ function can return a reference in a similar way as it returns a pointer. When returning a reference, be careful that the object being referred to does not go out of scope. So it is not legal to return a reference to local var. But you can always return a reference on a static variable.
You can't take the address of a reference, since attempting to do so would result in the address of the object being referred to, and thus you can never get a pointer to a reference. std::vector works with pointers to its elements, so the values being stored need to be able to be pointed to.
Since it is a const
member function, the return type cannot be non-const reference. Make it const
:
const std::vector<int> &VectorHolder::getVector() const { return myVector; }
Now it is okay.
Why is it fine? Because in a const
member function, the every member becomes const in such a way that it cannot be modified, which means myVector
is a const
vector in the function, that is why you have to make the return type const
as well, if it returns the reference.
Now you cannot modify the same object. See what you can do and what cannot:
std::vector<int> & a = x.getVector(); //error - at compile time! const std::vector<int> & a = x.getVector(); //ok a.push_back(10); //error - at compile time! std::vector<int> a = x.getVector(); //ok a.push_back(10); //ok
By the way, I'm wondering why you need such VectorHolder
in the first place.
it's not unusual to declare both const and mutable variants, like so:
std::vector<int>& VectorHolder::getVector() { return myVector; } const std::vector<int>& VectorHolder::getVector() const { return myVector; }
the underlying problem with your program is that you return a non-const reference from a const method.
std::vector<int>& VectorHolder::getVector() const { return myVector; // << error: return mutable reference from const method }
so you make it const using this form:
const std::vector<int>& VectorHolder::getVector() const { return myVector; // << ok }
and when this is in a non const method or the client holds a non-const reference, then you can legally use a non-const method:
std::vector<int>& VectorHolder::getVector() { return myVector; // << ok }
finally, you could return a value (in some cases):
std::vector<int> VectorHolder::getVector() const { return myVector; // << ok }
because the copy requires no mutation and provides no exposure to the internal data.
so you will end up declaring both variants quite often.
the results of declaring both are:
VectorHolder m; const VectorHolder c; m.getVector().size(); // << ok c.getVector().size(); // << ok - no mutation m.getVector().push_back(a); // << ok c.getVector().push_back(a); // << error: attempt to mutate const reference because the const vector is returned
so it all works out nicely (apart from the redundancy of the methods).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With