| X x = y; //the copy constructor is used, |
//but the prof. thinks the assignment operator is used.
This is clearly wrong; this is a declaration, not an expression, the equals sign is not an operator.
Since people want the "finer details" (and in case your prof is amenable to learning and is aware of the C++ standard),
X x = y;
is a declaration-statement ($6.7[stmt.dcl]), which consists of one simple-declaration ($7[dcl.dcl]/1), which consists of three parts: decl-specifier-seq
, and the semicolon. The init-declarator-list, obviously, consists of a single init-declarator, which is composed of two parts: the declarator
and the initializer
($8[dcl.decl]/1). The initializer grammar is in $8.5[dcl.init], which tells us that the syntax of this particular declarator is the equals sign followed by initializer-clause (which happens to be an id-expression)
So, the equals sign is not an assignment operator, it is a punctuator in the declaration grammar.
As for what's executed here and why, yes, this is, grammatically, copy-initialization from a nameless temporary obtained by copy-initialization performed as part of lvalue to rvalue conversion (which is why Disch's testcase selects the move constructor: the argument is an rvalue), and of course every compiler since very early 90s optimized this into a single copy constructor call under the copy elision rules "when a temporary class object that has not been bound to a reference would be copied/moved to a class object with the same cv-unqualified type" (from §12.8[class.copy]/13)