I'm doing the exercises from "Programming Principles and Practice using C++" and I found a class with this member function here:
const vector<string> &get_name() const { return name; }
where name is a vector: vector< string> name
;
The book presents 2 concepts so far (up to page 235):
return a const reference to prevent the function to change the returning value:
const vector<string> &get_name() { return name; }
a const member function that cannot modify the object. in this case, it would be like this:
vector<string> get_name() const { return name; }
Maybe I'm not getting this completely, but aren't those 2 concepts the same? Not wanting to change the "name" vector.
Why the need for both "const"?
Thanks to anyone taking the time to reply!
- return a const reference to prevent the function to change the returning value
- a const member function that cannot modify the object. in this case, it would be like this
This could have been a bit more clearer, I'll try my shot at explaining it better.
Returning a const reference prevent the returned object to be mutated by callers.
Here's an example:
// let get_name be `const std::vector<std::string>& get_name()`
np1.get_name().size(); // ok, size is a const function of vector
np1.get_name().push_back("hello"); // ERROR! push_back is not a const function of vector
So indeed, a caller cannot change the name
vector. The return type is const qualified.
However, if the function get_name
itself is not const qualified (not the return type), then it is allowed to change name from the class itself.
You see, member functions receive a hidden this
parameter, which is a pointer to the object being called on. The pointer can either point to a const object, or a mutable object. Here's the comparison:
// returning const ref, callers cannot change the name vector
const std::vector<std::string>& get_name() {
// The function receive a `this` that points to a mutable,
// we can change the name from the inside
this->name.push_back("another");
return name;
}
// the `this` pointer points to const -----v---v
const std::vector<std::string>& get_name() const {
this->name.push_back("another"); // ERROR! Cannot mutate member of const object
return name;
}
Const-qualified member function are really useful for the caller, as it knows that whenever this function is called, its state won't change.
For example, not only you know that the vector::size()
function won't mutate the vector, but the compiler guarantees it since it's a const qualified member function.
And for the last bit, the code you posted here:
vector<string> get_name() const { return name; }
This will not return a reference, but will make a copy. The caller can mutate the copy however it wants, but cannot mutate name
itself.
Here's an example of a copy mutated:
auto name_copy = np1.get_name();
name_copy.push_back("another name"); // works, we mutated the copy by adding an element