This question already has an answer here:
Why having const and non-const accessors?
(1 answer)
Closed 8 years ago.
So, I have to write two versions of the bracket operator for a class that I am writing.
Details:
The class has a private variable that is an array of strings.
The versions of operator[] differ in that one must be const, and the other not
I'm a little unsure how these two versions actually differ, and how when called, they will be able to be differentiated.
The one I currently have written
string& MyClass::operator[](unsigned int index);
simply returns the string at the index.
My question is, what is the point of having one const and one non-const? And how will they differ from each other?
EDIT:
Since I have to write these, will the code within each function be identical?
The correct overloaded versions are:
Access non const MyClass instance
std::string& MyClass::operator[](unsigned int index);
Access const or temp MyClass instance
const std::string& MyClass::operator[](unsigned int index) const;
The latter guarantees that access through a constant instance reference won't allow to modify the returned std::string reference, but to return a result though.
Implementation might need to consider that you could at least add new (default) string values to your container for currently unknown index values, and you'll need to decide how to handle unknown index values for const access (return empty string, throw exception, etc.).
Related
This question already has answers here:
Same function with const and without - When and why?
(7 answers)
Closed 6 years ago.
I was making a class for arrays to work as stacks and encountered upon two types of functions to return the top element. I cannot understand the difference between the two and how the compiler decides which one of the two to call. Beloww is the code for the two.
T & getTop() { //function 1
return arr[top - 1];
}
const T & getTop() const { //function 2
return arr[top - 1];
the 'top' variable points to the current empty cell in the array and T is the generic datatype.
Thank you for your help in advance.
I suppose your stack is called stack.
stack<T> s;
/*do something with it*/
s.getTop(); //will call the non const version
std::as_const(s).getTop() //will call const version
And similarly:
const stack<T> s;
s.getTop() //const version
So, if the type of the variable is not const, it will call non const version. Otherwise it will invoke const version.
You can see this answer for reference but in a few words for this specific case looks like is for tell to others methods won't change the logical state of the object.
A const T& reference doesn't allow to modify the referenced data. Notice that the second getTop() method is declared as const too to specify that the method doesn't modify the state of the instance on which this is called.
Two implementations are required to allow getting the top element from a context in which the instance that contains the array is const and at the same time allowing to modify the top element in contexts in which it's not const.
This is part of a bigger concept named const correctness, you can get additional info about it here, specifically:
What does “const X& x” mean?
What is a “const member function”?
What is the relationship between a return-by-reference and a const member function?
This question already has answers here:
What's the difference between passing by reference vs. passing by value?
(18 answers)
Closed 6 years ago.
I am a C++ newbie and I am working on a program that simulates a phonebook. Now, for the insert operation, function is defined as follows:
void PhoneBook::insert(const string& name, const string& number)
But it still works and inserts the contact as well if I remove the reference symbols. So, I am a little confused here, why do I need them?
void PhoneBook::insert(const string name, const string number)
void PhoneBook::insert(const string name, const string number)
Here you are constructing new strings with copy of all data. This is heavy operation.
void PhoneBook::insert(const string& name, const string& number)
Here you are passing reference to string (address of string), size of which is usually 4 or 8 bytes, based on platform, which is very light operation.
Also, when you pass reference, you are allowed to interact with object, which you are passed to function.
Rule of thumb - always pass by const reference, if variable is bigger than 8 bytes and you dont require explicit copy of object.
This question already has answers here:
Meaning of 'const' last in a function declaration of a class?
(12 answers)
Closed 6 years ago.
When coding a header file in C++ with method declarations, what's the difference between:
int getFoo() const;
const int getFoo();
const int getFoo() const;
First one, is for preventing this method changing any member variables of the object.
Second one, is for the return type (ie: constant integer)
Third one, is mix of both
Your first function operates on a const this pointer (that is; a const object that it can't change (or at least shouldn't)).
Your second function returns a constant integer - which is somewhat nonsensical since you can just assign it to a non-const variable and change it anyway. Besides, why does the function care if you change a POD type or not?
Your third function is just a combination of the first two. A function operating on a const object returning a const value.
This question already has answers here:
Meaning of 'const' last in a function declaration of a class?
(12 answers)
Closed 8 years ago.
I saw following code on c++ reference:
bool operator() (const int& lhs, const int&rhs) const
What does the last const do?
From the Const Correctness tutorial:
If you have a const object, you don't want to call methods that can
change the object, so you need a way of letting the compiler know
which methods can be safely called. These methods are called "const
functions", and are the only functions that can be called on a const
object. Note, by the way, that only member methods make sense as const
methods. Remember that in C++, every method of an object receives an
implicit this pointer to the object; const methods effectively receive
a const this pointer.
It might be worthwhile (spoiler: it is) to read through the whole article if you're new to the concept of constness.
It means the function (operator) does not change the object.
Effectively makes the "this" pointer a pointer to a const object. It means that members of the object cannot be modified in that method, nor can that method be invoked on a non-const object.
I'm currently writing a double linked list using dynamic memory in C++ for one of my classes. I've already got the code written, I just had a question.
Our professor required us to write both an
int& operator[](int position)
AND an
int operator[](int position) const
function.
What was the point in doing two functions for the same operator? I'm sure there's some kind of logic behind it, haha. Is it just so I can do a = arr[i] and also do arr[i] = a?
If you have a const list object, you should only be able to read values from it. If you have a modifiable one, you should be able to both read and write values. The first is done with the const version, which will be called for a const object.
When your object is const, you can only use the const version of the operator, which by virtue of being const doesn't allow modification of your object or returning non-cons pointers/references to internal members. So when your object is non-const you need a non-const operator that allows modifications so you can write foo[i]=n
1) The const variant is for reading, e.g. when you assign a value to a variable. The compiler will give you an error when trying to modify the list value at the specified index. Example for const is a = arr[i] as you wrote.
2) The non-const variant is usually used when you actually set the value at the certain index of the list. Although you could use this variant for getting a value as well. However, then the compiler would not raise an error when your intention is to just read and your code would accidentally write. That could lead to subtle bugs which you can avoid by using const for such cases. Example for non-const is arr[i] = a as you wrote.
If you have both versions present, the non-const version version will be called for reading when you execute the indexing on a non-const object.
Is it just so I can do a = arr[i] and also do arr[i] = a?
Yes, that's what it's for.
if you have a const or a non-const list then you can perform the a = arr[i] assignment;
the version of the operator that returns an int& is so that you can perform arr[i] = a, which of course requires a non-const list.
Its just if you have a const variable of your object, lets call it A const a; then you are only allowed to call const functions, like your const overload of operator [] (...) const, which only provides reading. You are not allowed to call the non const operator [] (...) in this case.
Where you have a doubly-linked list object that is defined with the const qualifier (commonly called "a const object") or referred to via a pointer-to-const or a reference-to-const, you want to be enable reading but not writing. The const-qualified operator does that.
Where you have an object that is defined without the const qualifier, or referred to via a pointer-to-non-const or a reference-to-non-const, you want to enable both reading and writing. The non-const-qualified operator does that.
So, the reason you bother writing two overloads is to implement both behaviours.
If you only wanted reading, regardless of constness, then you would only write the const version because const-qualified member functions can be used to interact with both cases, whereas non-const-qualified member functions can only be used on the names of non-const-qualified objects (or via a pointer-to-non-const or a reference-to-non-const).
If you only wanted operator[] to apply to non-const objects then you would only write the non-const-qualified version. This might seem strange, since you don't expect operator[] to need the object to be modifiable, but as it happens this is exactly what std::map does with operator[].