Considering the case where no copy-elision is involved (pre C++17).
From cppreference (again, suppose C++14):
Temporary objects are created in the following situations:
- binding a reference to a prvalue
- returning a prvalue from a function
- conversion that creates a prvalue
- lambda expression
- copy-initialization that requires conversion of the initializer
- list-initialization that constructs an std::initializer_list
- reference-initialization to a different but convertible type or to a bitfield.
int &&x = 5;
int x = 4;
2 + 2
int x = 2 + 2;
The C++14 standard says in 12.2 regarding Temporary objects ([class.temporary]):
Temporaries of class type are created in various contexts: binding a reference to a prvalue ([...]), returning a prvalue ([...]), a conversion that creates a prvalue ([...], 5.4), throwing an exception ([...]), and in some initializations ([...]).
MyClass obj = MyClass();,
MyClass() is a Explicit type conversion in functional notation, so it is a temporary object because it falls under "conversion that creates a prvalue".
This does not apply for the
int x = 4; because the rule refers to "class types" but
int is a "fundamental type".
Additionally 8.5 Initializers ([dcl.init]) defines the semantics of non-class type initializers in clause (17.8) as
Otherwise, the initial value of the object being initialized is the (possibly converted) value of the initializer expression. [...]
while for class types, (copy) constructors are invoked. So you need a (temporary) object to copy from for class types, but not for "other" types.
: actually N4296, but that shouldn't make a difference