06 Operator Overloading & Initialization
Overview: Initialization Semantics & Syntax Overloads
C++ distinguishes between initialization and assignment. This note covers member initialization list performance, operator overloading design rules, and
thispointer mechanics.
1. Member Initialization Lists vs. Assignment
A constructor can initialize its members using an Initialization List or by assignment inside the constructor body.
// Method A: Member Initialization List (Preferred)
Point(double a, double b) : x(a), y(b) {}
// Method B: Assignment inside body (Avoid unless necessary)
Point(double a, double b) {
x = a;
y = b;
}Why Initialization Lists are preferred:
- Performance (Zero Double-Initialization): Method B first calls the default constructor for
xandy, then overwrites them using the assignment operator. Method A constructs them in-place with the correct values immediately. - Mandatory cases:
constmembers and reference variables (Type&) must be initialized via the initialization list because they cannot be assigned after construction.
The Declaration Order Gotcha:
Members are always initialized in the order they are declared in the class definition, regardless of their order in the initialization list.
class Foo {
int a;
int b;
public:
Foo(int x) : b(x), a(b + 1) {} // WARNING: 'a' is initialized first with uninitialized 'b'!
};2. Operator Overloading Design Rules
Operator overloading provides clean syntax for custom types.
Point operator+(const Point& rhs) const;- Why the
const Point& rhsparameter? Prevents copying the right-hand side object (performance) while guaranteeing it won’t be modified (safety). - Why is the function marked
constat the end? Guarantees the operation does not modify the left-hand side object (allowsup + rightwithout alteringup).
3. The this Pointer & Chain Assignments
Within any non-static member function, this is a hidden pointer pointing to the active object instance.
For compound assignment operators (like +=), it is standard practice to return a reference to the modified object (*this):
Point& Point::operator+=(const Point& rhs) {
x += rhs.x;
y += rhs.y;
return *this; // Returns a reference to the modified object
}Why return a reference?
Returning Point& allows you to chain operators (e.g. (p1 += p2) += p3) and avoids the overhead of copy-constructing a temporary object during assignment.
💻 Conceptual Code Demonstration
#include <iostream>
class Vector2D {
public:
double x;
double y;
const double limit; // Must be initialized in initializer list
// 1. Initializer List constructor
Vector2D(double xVal, double yVal, double lim) : x(xVal), y(yVal), limit(lim) {}
// 2. Binary addition operator overload
Vector2D operator+(const Vector2D& rhs) const {
double newX = x + rhs.x;
double newY = y + rhs.y;
return Vector2D(newX > limit ? limit : newX,
newY > limit ? limit : newY,
limit);
}
// 3. Assignment operator overload returning reference
Vector2D& operator+=(const Vector2D& rhs) {
x += rhs.x;
y += rhs.y;
if (x > limit) x = limit;
if (y > limit) y = limit;
return *this; // Dereference pointer to return reference
}
};
int main() {
Vector2D a(10.0, 5.0, 20.0);
Vector2D b(5.0, 10.0, 20.0);
// Operates as: a.operator+(b)
Vector2D result = a + b;
std::cout << "Result: " << result.x << ", " << result.y << '\n';
// Chained assignment operates as: (a.operator+=(b)).operator+=(b)
a += b;
std::cout << "a updated: " << a.x << ", " << a.y << '\n';
return 0;
}