This is not limited to C++. All widely-used, "old" programming languages shun away from adding keywords, because it can break previously working code. Python is the same way too.
I'd say that in the case of pass-by-reference, the symbol they reused makes sense: references are basically syntactic sugar for a limited form of "automatically-dereferencing pointers", meaning that creating a reference involves taking an address, and so & would be the logical choice.
Personally I don't think it's so useful of a feature; it saves typing a few asterisks but obscures the fact that you're actually modifying some other variable.
Personally I don't think it's so useful of a feature; it saves typing a few asterisks but obscures the fact that you're actually modifying some other variable
There are many real-world use cases where references are exactly the right feature, and the const-ness of that reference should make the intentions clear.
Performance-critical code is one place where not having the ability to pass large objects around by reference would be a performance killer. References allow us to avoid making unnecessary copies.
Yes, you can accomplish the same thing with a pointer, but raw pointers are much less common in modern C++. It's not just syntactic sugar; a reference conveys information. When writing a function you can eschew null pointer checks when using references, whereas a function taking a (raw) pointer should handle the null pointer case since technically you can call foo(nullptr) and it'll compile.
With a reference bar must exist for the foo(bar) expression to compile when calling void foo(const Bar& bar), so it's safer, simpler code.
Without references there would be tons of problems.
How would you implement a copy constructor or copy assignment operator without them? Those two things are necessary for user defined types to be able to be treated like built in types, which is necessary if you want templates to be fully generic, which is essential for all the STL containers.
Given that references are implemented with pointers, those special functions are really taking pointer parameters anyway. Syntax-wise things might look a little different, but I don't think it poses much of a real problem.
But you lose the constant syntax that allows STL containers to work. vector<int> and vector<Person> work because vector can be templated, and
int i1;
int i2 = i1;
Person p1;
Person p2 = p1;
both have the same syntax. If suddenly p2 = p1 no longer compiles and you have to do p2 = &p1 that looks really weird because the two sides of the = have different types and vector<Person> no longer will compile. On the other hand if we say all overloaded operators automatically convert operands to their addresses, then we are sort of back where we started with references: you can modify a variable inside a function without having to say &. Only this would be much less flexible than what we have now because sometimes you want an overloaded operator to take something by value, but wouldn't be able to do it.
There are 3 meanings of static, 2 meanings of auto, 2 meanings of delete, 2 meanings of default.