TGViewer
C++: Хроники Дурки🚑 C++: Хроники Дурки🚑 @cpp_durka · 916 subscribers
Post #41 938
Ответ: два раза.

А все почему? А вот почему:

У нас есть конкретные правила, когда 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 - закрываю ноут и перестаю копать дальше....
godbolt.org Compiler Explorer - C++ template<class T> inline constexpr T id(T x) { return x; } struct S { int value_; explicit S(int i) : value_(i) { puts("int-ctor"); } S(S&&) noexcept { puts("move-ctor"); } ~S() { puts("dtor"); }; static S make() { return S(42); } };…
  • 😁 8
  • 💊 7
  • 🔥 2
  • 🥴 2
More from @cpp_durka
  1. Sep 8, 2026Мошенники заставили пенсионерку из Москвы переписать квартиру на Rust
  2. Aug 31, 2026Всяко разное болезненное есть в С++, из всего болезненного одно из самых болезненных - это…
  3. Aug 24, 2026Если кто не знаком с библиотекой nlohmann/json - она прекрасна. Мои мысли о том, как должн…
  4. Aug 21, 2026#толькосвоимемы Код взят тут. if (dim == 0) idx_dim = i0; else if (dim == 1) idx_dim = i1;…
  5. Aug 17, 2026Ладно, искать баги в компиляторах весело, но недостаточно. Давайте поиграемся в чуть более…
  6. Aug 10, 2026Ладно, разумеется прошлый пост был набросом. Никогда не обновляйте компиляторы без очень с…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →