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 fun
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).
The function getVector
can be declared as const
. It returns a reference that can be modified, so while the actual function doesn't modify anything in the class, the caller will be able to modify internal data.
Declare it as:
std::vector<int>& getVector();
If you want a function to return a vector that can't be modified, the use the const
modifier on both the vector and the function:
const std::vector<int>& getVector() const;
The reason is that a const member function should only return const references. This is because in a const function, every data member becomes constant.
Therefore you have to declare the getVector() this way:
std::vector<int> &VectorHolder::getVector() const;