For operators like operator+ and operator+=, why is it that when it comes to operator+= we return a reference? Where with the operator+ we return a copy of a temporary object? Why don't they both return the same things, either both return a copy or a reference?
The + operator creates a new object from two parameters, while the += operator modifies one of the operands. I'll answer this partly by asking you a questions back: If operator + returns a reference, what should it return a reference to? Keep in mind while answering this that, in the syntax c=a+b, you are responsible for creating c from a and b, and neither a nor b shall be modified inside the operator. Try implementing operator + by returning a reference.
The += operator is different in that in the syntax a+=b, the object a is modified by b inside the operator. Nothing has to be returned in this case, not even a reference, but a reference is commonly returned in order to chain operators or have access to the modified value directly in the same expression.
Also I have a few questions when it comes to the copy assignment operator:
MyObject &MyObject::operator=(const MyObject &obj)
1. Why is there a destructor called when there is no local object being created in the code? What is actually being destroyed here?
Use the debugger to break where the destructor is actually called to identify which object is destructed where. Unless I misunderstand you, you are right that no object should be destructed in this case.
2. When I was reading up on copy assignment operators, I saw that I should have the self-check guard in order to prevent memory leaks and dangling pointers when it comes to objects that use dynamic memory allocation. But I'm wondering do I need this if I know my class is not going to have any dynamic memory stuff? Or is this something I should do just as a "good practice"?
You could do it for performance reasons as well; if the object is expensive to copy (may include other reasons than just dynamic resources) then it may be faster to check for self-assignment than to blindly make an unnecessary self-copy. It all depends on your use case, if you do self-assignment often enough and whether it is worth checking for it or not.
3. When read about this operator and dynamic memory allocation, the topic of the "copy swap" idiom comes about. Should I only follow this idiom when dealing with dynamic memory, because an exception could get thrown when trying to allocate data? Or is this something I should just practice as well?
As far as I understand, copy-and-swap is mostly for exception safety reasons. If your assignment cannot fail, then copy-and-swap serves no additional purpose for exception safety. This is, again, not necessarily tied to dynamic resources.
Self-assignment and copy-and-swap are tools you should be aware of and know how and when to use, and equivalently know when they aren't needed. Nothing breaks if you use them when it's not needed, but sometimes the tools or some logically equivalent protection is necessary; for example, if self-assignment breaks your objects, you can either add a self-assignment tests or re-structure your program or algorithms such that self-assignment never happens in the first place.