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


#1

А зачем вы используете КК вдобавок к основному конструктору? Следует использовать только основной конструктор: fstream in("input.txt");. С auto хотелось повыделываться? Забыли про то, в каких случаях вызывается КК? Не научит преподаватель — научит жизнь…


Алгоритмы на графах (осень 2015)
#2

@xamgore Сколько раз перед этим постом я Вам говорил так не писать? Раз пять? :slight_smile: Вот видите уже и другие преподаватели говорят тоже самое!


#3

@Ulysses, вы не правы, copy constructor не вызывается в данном случае, пруфы.

А причины, почему я так пишу, непонятны крестоносцам:

  • Я пришёл из java и привык к записи вида Type t = new Type();
  • Я попробовал автоопределение типа в C# var t = new Type();
  • Наиболее близкая к этому конструкция в C++ auto t = Type();
  • Единый стиль, всё равно где-то будет писаться что-то вроде auto t = getType();
  • Просматривая список переменных, я вижу сначала название, потом тип;
  • Я могу легко изменить факт, где будет выделена память, на стеке или в куче:
auto object = queue<int>();
auto& object = *new queue<int>();  // *new и &, без копипаст

#4

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

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


#5

Обоснуй.


#6

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

Жирное ИМХО.


#7

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


#8

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

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

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


#9

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

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

#10

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


#11

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


#12

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


#13

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


#14

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


#15

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


#16

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


#17

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


#18

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


#19

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

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


#21

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

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

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

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


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

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

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

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