The idea
Line 1 makes two Vec2 objects, a and b, each holding an x and a y. For int, the + sign already means add. For a class you write yourself, a + b means nothing until you give it a meaning.
Operator overloading means writing a function whose name is the word operator plus the symbol, such as operator+. When the compiler meets a + b and an operand is a Vec2, it turns the expression into the call operator+(a, b).
Writing operators
operator+ reads both objects and builds a new Vec2: x is 1 + 3 = 4 and y is 2 + 4 = 6. It returns that new object, and it becomes c. Nothing is written into a or b.
The & in const Vec2& makes the parameter a reference: a and b are passed without being copied. const promises the function will not change them. The sum is a brand new object, so operator+ returns it by value.
Line 3, a += b, calls a member function: a.operator+=(b). It adds b into a itself, so a becomes {4, 6}. It returns *this, a reference to a, just as += on an int gives back the variable.
More operators
Line 4, a == c, calls a.operator==(c). Declared = default (new in C++20), it compares x with x, then y with y. Both match, so it returns true. The compiler also rewrites a != c as !(a == c) for you.
Line 5, std::cout << c, calls operator<<(std::cout, c). The left operand is the stream, not a Vec2, so this is a free function: one written outside the class. It prints (4, 6) and returns the stream, so more << can follow.
You cannot invent symbols like **, change precedence or the number of operands, or redefine + for two ints. The operators ::, ., .* and ?: cannot be overloaded. Good style: keep each symbol's usual meaning.
What happens
;; step 1/8 · objects
struct Vec2 { int x, y; };
1 Vec2 a{1, 2}, b{3, 4};
a { x: 1, y: 2 }
b { x: 3, y: 4 }
without operator+: a + b → compile error
g++: no match for 'operator+' (operand types are 'Vec2' and 'Vec2')
For an expression a @ b where an operand has class or enumeration type, the compiler looks for both a member a.operator@(b) and a free operator@(a, b), and overload resolution picks the best match. Defaulted comparisons (= default) and the rewriting of a != b into !(a == b) are both new in C++20. Before C++20 you wrote operator== and operator!= by hand.