Somewhat related to Why is copy constructor called instead of conversion constructor?
There are two syntaxes for initialization, direct- and copy-initialization:
Take the following example:
struct X
{
X(int);
X(const X&);
};
int foo(X x){/*Do stuff*/ return 1; }
X x(1);
foo(x);
In the compilers I tested, the argument to foo was always copied even with full optimization turned on. From this, we can gather that copies will not/must not be eliminated in all situations.
Now lets think from a language design perspective, imagine all the scenarios you would have to think about if you wanted to make rules for when a copy is needed and when it isn't. This would be very difficult. Also, even if you were able to come up with rules, they would be very complex and almost impossible for people to comprehend. However, at the same time, if you forced copies everywhere, that would be very inefficient. This is why the rules are the way they are, you make the rules comprehensible for people to understand while still not forcing copies to be made if they can be avoided.
I have to admit now, this answer is very similar to Suma's answer. The idea is that you can expect the behavior with the current rules, and anything else would be too hard for people to follow.