О конструкторах копии

Очень нехорошо тянуть привычки из другого языка.

Это не java, тут есть неопределенное поведение, так что доказательством будет ссылка на стандарт. Но так-то ты прав [16.2.5][1]. [1]: http://mazonka.com/shared/Straustrup4th.pdf

Обоснуй.

У каждого языка свои принятые нормы: вот именаПеременныхВJava, например. И чтобы другим не приходилось сидеть целую ночь и разбирать твой код, то нужно придерживаться этих норм. Я что-то не представляю многолетний живущий проект с 100000 строк кода, в котором мешаются друг на друге GetCurrentTime() и get_current_time().

Жирное ИМХО.

В Java мире есть конвенция 1995 года, которая устанавливает стандарт форматирования кода для всех. В C++ такой нет.

Нет, родной мой, не правы вы. Выбрасывание КК является частным случаем оптимизации известной как RVO (про это тоже рассказывалось на втором курсе), но оптимизации применяются компилятором после того, как пройдены стадии синтаксического и семантического анализа. А в вашем идиосинкразическом коде эти стадии завершаются ошибкой, так как горе-программист пытается вызвать несуществующий КК.

Резюме: не смотря на то, что во всех топовых компиляторах КК в подобных случаях выбрасывается на стадии оптимизации — если такого КК вовсе нет, то будет выдана ошибка компиляции.

Желаю успехов в освоении C++!

И правда, без RVO копирующий конструктор будет вызван. У Страуструпа как-то корявенько этот момент написан. У него: чтобы проинициалицировать объект нужно написать

Date date1 = Date(1, 2, 3);
Date date2(4, 5, 6); // сокращенная форма

Это не сокращённая форма, это единственный разумный способ. А остальное это нездоровые фантазии писать так, как в других языках.

Я не спорю, это цитата из Страуструпа, у него написано, что это сокращенная форма. И в английской, и в русской версии.

Вы правда, учась на 3м курсе, считаете книгу Старуструпа стандартом или я чего-то не понял?

1 лайк

Я что-то не понял, я где-то сказал, что книга Страуструпа - это стандарт языка С++?

В приведённой цитате вы сказали про стандарт и сослались на С. Это очень непоследовательно.

Я сослался, потому что доверяю этой книге и мог быстро в ней найти нужную тему. Это первый раз, когда нашел там несоответствие стандарту, и то - это не несоответствие, а нечеткое описание. Непоследовательно - ок, согласен.

У него много недочётов в книге: слишком большая работа, чтобы написать её идеально от начала до конца. Надо думать головой и использовать разные источники, а не слепо верить одному авторитету. Я это не конкретно про вас, а вообще…

Я вашу фразу воспринял в точности как @Ulysses и был крайне удивлен, увидев Страуструпа.

Я не пойму, а что мешает в С++ писать Type* t = new Type(); ? Сильно звездочка глаза режет? И полностью поддерживаю утверждение о том, что не надо переносить привычки с одного языка на другой. Как интересно можно писать на asm в стиле Java? :wink:

Странно, что такие проблемы возникают. Обсуждали RVO, &&-семантику и т.д. в прошлом году.

А чего все к Страуструпу так прицепились? Неужели он настолько не катируется, или у всех слово стандарт такую реакцию вызывает?

А не могли бы ещё раз объяснить, что вы имели в виду? Я показал пример, где есть copy- и move- конструкторы, и указал, что КК не будет вызван. Вы сказали, что я читер, и этот пример различается с оригинальным постом, потому что в fstream нет КК.

Хорошо, вот пример, где copy удалён, как и в fstream, и есть только один move-конструктор. На это вы сказали, что я бездарь, и в нём точно происходит ошибка: вызов несуществующего КК. Это действительно справедливо в случае, где нет ни copy-, ни move-конструктора.

Возвращаясь к моему примеру, где нет КК но есть МК, ошибки не возникает, несмотря на отсутствие copy-конструктора. Напомню:

Я пытался вызвать несуществующий КК, а всё-таки получил RVO. Согласно вашим словам, должна была произойти ошибка компиляции. Поправьте, если что-то не так.


Таким образом:

  • Вы назвали меня горе-программистом;
  • RVO будет проведена при наличии move- и / или _copy-_конструктора;
  • Использовать подход auto t = Type() для всех случаев нельзя;
  • Да, я хотел повыделываться, но не в ущерб эффективности;
  • Вышел из воды сухим, потому что был уверен, в том что пишу;
  • И вы, и я правы, просто мы о разном.

Напомню, что изначально упор делался на наличие move-конструктора в используемых мной классах из стандартной библиотеки:

auto in = fstream("input.txt");

Я просто объяснял ошибку, котора была получена вами: там вызывался КК. Ваши фантазии на тему у меня желания обсуждать нет.

Вопрос почему там вызывался именно КК, а не move-КК, очень легко гуглится, вы могли бы уже сами это давно сделать, а не разводить пространную дискуссию. Ответ: потому что в GCC не было реализации move-КК до версии 5.0 (которая ещё мало где установлена).

Не смотря на то, что в актуальных версиях компиляторов эта проблема решена, писать так значит писать на каком-то другом языке. Кроме того, это сломается на первом классе, у которого не будет ни КК, ни move-КК: поверьте, таких классов достаточно много. Это все классы, владеющие ресурсами (типа файлов), из библиотек, написанных до появления move.

1 лайк

Мне кажется, здесь нужно отделить две вещи.

  1. Стоит ли писать такую конструкцию. ИМХО, конечно нет.
  2. Вызов КК и МК. Считаю, что шпынять студентов за то, что они не додумались глянуть версию компилятора и вспомнить, а когда же эта фича появилась в g++, мне видится не правильным.

Эти две вещи нельзя разделять: если бы выполнялось первое, не пришлось бы думать про второе. Именно про первое я и «шпыняю» большую часть. Про второе я написал только то, что это гуглится. Но вы видимо прочли что-то другое.