А все почему? А вот почему:
У нас есть конкретные правила, когда copy-ellision разрешен, и когда явно запрещен. И там один абзац, и в абзаце этом черт ногу сломит. Нас интересует вот это
with automatic storage duration (other than a function parameter or a variable introduced by the exception-declaration of a handler)
Нам явно запрещено оптимизировать параметры функции. А вот return мы оптимизировать можем (RVO).
Вот такая вот интересная загогулина...
Из интересного, немного по-разному выглядит порядок деструкторов в MSVC и gcc/clang:
MSVC:
int-ctor
move-ctor
dtor
move-ctor
dtor
dtor
gcc:
int-ctor
move-ctor
move-ctor
dtor
dtor
dtor
clang:
int-ctor
move-ctor
move-ctor
dtor
dtor
dtor
Но ситуация еще забавнее. В предыдущий пост в комменты прилетело объявление move-конструктора с ключевым словом explicit.
Обычно я так не объявляю, но давайте поиграемся с этим.
explicit простыми словами запрещает использовать конструктор без явного его вызова.
struct S {
int value_;
explicit S(int i) : value_(i) { puts("int-ctor"); }
explicit S(S&&) noexcept { puts("move-ctor"); }
explicit S(S const &) noexcept { puts("cpy-ctor"); }
~S() { puts("dtor"); };
};
S id(S x) { return x; }
S id_cpy(const S& x) { return x; }
Вот так делать при этом нельзя:
error: class "S" has no suitable copy constructor
Что происходит. Это очень старая штука - компилятор сначала подставляет конструктор копирования, а уже потом применяет оптимизации (RVO, copy-ellision и т.п.), и тогда копирование уходит.
Мы можем в этом случае объявить функцию немного иначе:
S id(S x) { return S(x); }
S idm(S x) { return S(std::move(x)); }
В первом случае вызывается явно конструктор копирования, во втором - move конструктор.
При этом MSVC такие штуки
gcc и clang компилируют, но не могут оптимизировать конструкторы по тем же самым причинам.
int-ctor
move-ctor
move-ctor
dtor
dtor
dtor
Но в таком примере, по любимой традиции, выпендрился icc. У него конструкторов 3, а деструкторов - 8.
int-ctor
move-ctor
dtor
move-ctor
dtor
dtor
dtor
dtor
dtor
dtor
dtor
И я вообще не понимаю, что в "голове" у icc, я с самого начала как натыкаюсь на что-то в icc - закрываю ноут и перестаю копать дальше....