In linea di principio potresti avere ragione tu, dal momento che il nome dell'oggetto inizia ad esistere già da prima dell'inizializzazione - leggi qui; d'altra parte, lo standard non è così chiaro in proposito, in effetti il passaggio dell'oggetto non ancora costruito al costruttore di copie si potrebbe qualificare come l'inizializzazione di un reference con un oggetto non valido (in quanto non ancora costruito). Diciamo che è un'area grigia del linguaggio.

Questo a livello di standard. Per quanto riguarda il codice effettivamente generato, dato che, come detto, il nome dell'oggetto può essere usato nell'espressione di inizializzazione, il compilatore in linea di massima genererà codice che si comporta come hai avuto modo di sperimentare (se lo standard non proibisce esplicitamente qualcosa chi scrive compilatori in genere non sta a creare "casi ad-hoc" per cose così di nicchia).

In ogni caso, cercare di difendere il proprio codice in maniera così maniacale è solo una perdita di tempo: se qualcuno chiama il costruttore di copie in quella maniera sa di stare andando quasi sicuramente in undefined behavior, dato che sta passando in giro un oggetto ancora non costruito. Se il codice chiamante vuole esplicitamente spararsi sui piedi che faccia pure.

Il test che dici invece ha senso nel caso dell'operatore di assegnamento, dove è decisamente possibile (inavvertitamente o meno) assegnare un oggetto a sé stesso. Ma in verità l'unico modo per gestire correttamente costruttore di copie, operatore di assegnamento e distruttore è usare l'idioma del copy and swap, tutti gli altri sistemi in genere hanno falle di vario tipo.