Comparing i++ and ++i
Modern compilers perform extensive code optimization to generate efficient binary executables. These optimizations often obscure the original C/C++ semantics, making it imposible to reconstruct the source code from compiled binaries.
When examining assembly output for standalone increment operations:
int counter = 0;
// Postfix increment
counter++;
// Prefix increment
++counter;
The ganerated assembly instructions are identical:
mov dword ptr [counter],0
mov eax,dword ptr [counter]
add eax,1
mov dword ptr [counter],eax
mov eax,dword ptr [counter]
add eax,1
mov dword ptr [counter],eax
Overloading Increment Operators
Both global functions and class member functions can overload increment operators. The prefix version requires no additional parameters, while the postfix version uses an int parameter as a placeholder for differentiation.
#include <iostream>
class Counter {
private:
int value;
public:
Counter(int initial) : value(initial) {}
int getValue() const { return value; }
// Prefix increment: increment then return
Counter& operator++() {
++value;
return *this;
}
// Postfix increment: return then increment
Counter operator++(int) {
Counter temp(value);
value++;
return temp;
}
};
int main() {
Counter c1(0);
Counter c2(1);
std::cout << (c1++).getValue() << std::endl; // 0
std::cout << c1.getValue() << std::endl; // 1
std::cout << (++c2).getValue() << std::endl; // 2
return 0;
}
Performance Considerations
For primitive types, prefix and postfix increments exhibit similar performance after compiler optimization. For class types, prefix increment is more efficient as it avoids creating temporary objects.
Complex Number Implementation
Header file (Complex.h):
#ifndef COMPLEX_H
#define COMPLEX_H
class Complex {
private:
double real;
double imag;
public:
Complex(double r = 0, double i = 0);
double getReal() const;
double getImag() const;
double modulus() const;
Complex operator+(const Complex& other);
Complex operator-(const Complex& other);
Complex operator*(const Complex& other);
Complex operator/(const Complex& other);
bool operator==(const Complex& other);
bool operator!=(const Complex& other);
Complex& operator=(const Complex& other);
Complex& operator++(); // Prefix
Complex operator++(int); // Postfix
};
#endif
Implementasion (Complex.cpp):
#include "Complex.h"
#include <cmath>
Complex::Complex(double r, double i) : real(r), imag(i) {}
double Complex::getReal() const { return real; }
double Complex::getImag() const { return imag; }
double Complex::modulus() const {
return std::sqrt(real * real + imag * imag);
}
Complex Complex::operator+(const Complex& other) {
return Complex(real + other.real, imag + other.imag);
}
Complex Complex::operator-(const Complex& other) {
return Complex(real - other.real, imag - other.imag);
}
Complex Complex::operator*(const Complex& other) {
return Complex(real * other.real - imag * other.imag,
real * other.imag + imag * other.real);
}
Complex Complex::operator/(const Complex& other) {
double denominator = other.real * other.real + other.imag * other.imag;
return Complex((real * other.real + imag * other.imag) / denominator,
(imag * other.real - real * other.imag) / denominator);
}
bool Complex::operator==(const Complex& other) {
return (real == other.real) && (imag == other.imag);
}
bool Complex::operator!=(const Complex& other) {
return !(*this == other);
}
Complex& Complex::operator=(const Complex& other) {
if(this != &other) {
real = other.real;
imag = other.imag;
}
return *this;
}
Complex& Complex::operator++() {
++real;
++imag;
return *this;
}
Complex Complex::operator++(int) {
Complex temp(real, imag);
++real;
++imag;
return temp;
}
Usage example:
#include <iostream>
#include "Complex.h"
int main() {
Complex num(0, 0);
Complex result1 = num++;
Complex result2 = ++num;
std::cout << "Result1: " << result1.getReal() << ", "
<< result1.getImag() << std::endl; // 0, 0
std::cout << "Result2: " << result2.getReal() << ", "
<< result2.getImag() << std::endl; // 2, 2
return 0;
}