Article::Article
In C++ as in many language, you can use the ++
or --
operators to increment or decrement a variable representing a number. It can be placed before the variable, in the case this is the prefix operator also called postfix operators, or after, then it is a postix operator also called suffix operators.
int i = 0;
// Pre increment
++i;
// Post increment
i++
// Pre decrement
--i;
// Post decrement
i--
The difference between those operators
The first, and well known, difference, aside from the fact that one is placed before and the other is placed after, if that the prefix operators will be executed before the rest of the expression and the postfix operators will be executed after.
Here's a little example to see it better:
#include <iostream>
int main()
{
int i = 0;
std::cout << ++i << std::endl; // Print 1
std::cout << i++ << std::endl; // Also print 1
std::cout << i << std::endl; // Print 2
}
Note: don't do this because it is undefined behavior:
// Examples taken from cppreference
// https://en.cppreference.com/w/cpp/language/eval_order
i = ++i + i++; // undefined behavior
i = i++ + 1; // undefined behavior
i = ++i + 1; // undefined behavior
++ ++i; // undefined behavior
f(++i, ++i); // undefined behavior
f(i = -1, i = -1); // undefined behavior
f(i, i++); // undefined behavior
a[i] = i++; // undefined bevahior
The second one is that for the built-in versions of theses operators, the pre increment operator directly increment the variable and returns a reference, but for the post decrement operator, it makes a copy, increment it and then return it. Usually when overloading an operator, people tends to keep it the same way and that's why some people will argue that the pre increment operator is more optimized. But when overloading it, it is totally possible to take a reference as parameter instead of a copy, and also if the type is trivial, all compilers optimize it with only the -O1
flag. You can see it on compiler explorer: here the unoptimized version and here the optimized version.
Overload
The pre increment operators
That's the easiest one, here's how to do it:
struct Int
{
// Overload it as a member function
Int& operator++()
{
++i;
return *this;
}
int i;
};
// Overload it as free Function
Int& operator--(Int& fi)
{
--fi.i;
return fi;
}
The post increment operators
It is done the example same way, but you add an integer argument. This argument is only used to differentiate both overloads, its value will always be 0.
struct Int
{
// Overload it as a member function
Int operator++(int)
{
++i;
return *this;
}
int i;
};
// Overload it as free Function
Int operator--(Int fi, int)
{
--fi.i;
return fi;
}
The chaotic usage
When I said just above the value of the integer for the postfix operator will always be 0, that's not exactly true, if you use the operator overload like a regular function like this, it can have a value:
#include <iostream>
struct Int
{
// Overload it as a member function
Int operator++(int n)
{
i += --n;
return *this;
}
int i;
};
// Overload it as free Function
Int operator--(Int fi, int n)
{
fi.i -= ++n;
return fi;
}
int main()
{
Int i{5};
auto other_i = i.operator++(5);
std::cout << other_i.i << std::endl; // 5 + 5 -1 = 9
}
I hope that nobody is really doing this.
Article::~Article
The increment and decrement operators have no secrets for you anymore. You know what they do, how to use them and how to overload them.
Top comments (0)