Разве оптимизация возвращаемого значения (RVO) не является ошибкой?

Возможно, я задаю глупый вопрос, но я посмотрел страницу википедии для RVO здесь и не смог остановиться интересно, является ли это поведение неправильным. Я попробовал это на своей машине, и RVO полностью включился, несмотря на уровень оптимизации. Что, если в конструкторе действительно происходит что-то БОЛЬШОЕ? Я знаю, что не должно, но что, если? Я не могу понять, почему RVO все еще происходит, когда в конструкторе есть побочные эффекты.

РЕДАКТИРОВАТЬ: -fno-elide-constructors кажется, останавливает RVO. Но вопрос остается.

EDIT2: А если серьезно, то сколько людей знают о чем-то подобном? Это может быть в стандарте, но это все еще очень уродливая функция, как я ее вижу. По крайней мере, компиляторы должны отключить его по умолчанию и предоставить переключатель для людей, которые знают об этом. :)

РЕДАКТИРОВАТЬ 3: Я все еще настаиваю на том, что это действительно плохо. :). Я не думаю, что знаю какое-либо другое языковое ограничение, подобное этому, которое напрямую противоречит синтаксису языка. Все остальное выдает либо ошибки компилятора, либо компоновщика, верно?


person nakiya    schedule 11.10.2010    source источник
comment
Лично я считаю, что РВО - это мерзость.   -  person John Dibling    schedule 11.10.2010
comment
Можете ли вы придумать хороший вариант использования нетривиальных побочных эффектов в конструкторе копирования? У меня нет, навскидку. Как правило, их вызывают за кулисами, и очень легко ошибиться, рассчитывая, когда их вызовут. Для меня это очень веская причина, чтобы исключить побочные эффекты.   -  person David Thornley    schedule 11.10.2010
comment
У меня нет причин помещать побочные эффекты в конструктор копирования. :)   -  person nakiya    schedule 11.10.2010
comment
@nakiya: Верно. Я не беспокоюсь о возможных подводных камнях при выполнении того, что я уже считаю подводным камнем. Что касается поддержки RVO, то это позволяет исключить некоторые копии, которые могут занимать много времени и выполняться часто, что позволяет программам на C++ быть более эффективными (и в списке критериев проектирования разрешение на эффективность было выше, чем предотвращение неправильного использования).   -  person David Thornley    schedule 11.10.2010
comment
Разве он не должен работать прямо перед оптимизацией? Я не против RVO, я думаю, что основная причина этого в том, что без него все эти контейнеры в стандартной библиотеке были бы довольно громоздкими. Но вы все равно можете указать ключевое слово или ключи компилятора, не так ли?   -  person nakiya    schedule 11.10.2010
comment
@nakiya: В какой-то степени да, хотя я бы сказал, что код, основанный на побочных эффектах в конструкторах копирования, вероятно, работает неправильно. Тем не менее, оптимизация очень неуклюжая, чтобы вручную вводить ее позже. Одной из целей разработки C++ было устранение неоправданной неэффективности, а необходимость запуска потенциально дорогостоящего конструктора копирования без необходимости является неоправданной неэффективностью. Я не говорю, что RVO подходит для любого языка, но он согласуется с философией C++.   -  person David Thornley    schedule 11.10.2010
comment
@David: я могу согласиться с вами, что иметь конструктор копирования с побочными эффектами - очень плохая практика. Никаких аргументов по этому поводу. Но любой, кто использовал классы в C++, в тот или иной момент использовал конструктор копирования. Я не понимаю, почему такая базовая функциональность может быть настолько подвержена ошибкам. Я уже некоторое время использую C++, только сейчас я наткнулся на эту тему RVO. Хотя это может быть отчасти из-за моего невежества, я не думаю, что это очень «горячая» тема. : Д. Мир.   -  person nakiya    schedule 11.10.2010


Ответы (3)


Стандарт предписывает, что операции, связанные с наблюдаемым состоянием программы, не должны быть оптимизированы, за исключением создания копии в определенные обстоятельства. Вы не должны полагаться на выполнение конструкторов копирования, даже если они имеют побочные эффекты, которые вы ожидаете увидеть (например, вывод на консоль).

person sbi    schedule 11.10.2010
comment
Так вот почему передача по значению лучше? - person nakiya; 11.10.2010
comment
Это одна из причин, почему передача по значению может быть лучше. Это тоже не универсальный совет. Иногда передача по значению обеспечивает оптимизацию, которая была бы невозможна при передаче по ссылке, но в некоторых случаях она также может быть медленнее. :) - person jalf; 11.10.2010
comment
Кроме того, я думал, что boost::shared_ptr зависит от тех же двух функций для подсчета ссылок. Что там происходит? - person nakiya; 11.10.2010
comment
@nakiya: в случае shared_ptr создание дополнительного временного объекта, который уничтожается почти сразу, приводит к увеличению, а затем уменьшению счетчика ссылок, поэтому счетчик ссылок остается одинаковым независимо от того, происходит оптимизация или нет. - person Doug; 11.10.2010
comment
@nakiya: ну, если конструктор копирования оптимизирован, то это потому, что копия оптимизирована и вообще никогда не создается. И тогда ничего страшного, что счетчик ссылок не увеличивается (по сути, это единственное правильное поведение). ;) - person jalf; 11.10.2010
comment
Компилятору по-прежнему не разрешено просто выполнять memcpy вместо вызова конструктора копирования. Если он копирует объект, он должен сделать это правильно, используя конструктор копирования. Но можно полностью исключить копирование, а затем также исключить вызов конструктора копирования. - person jalf; 11.10.2010
comment
Серьезно, сколько разработчиков C++ прочитали каждый уголок стандарта? Я, например, точно нет :(. Разве не просто опасно оставлять что-то подобное в качестве поведения по умолчанию? Я имею в виду, что это может привести к ошибкам в программах, и люди просто потратят время. Я не говорю, что это распространено, но мне это не нравится Просто то, что я думаю. - person nakiya; 11.10.2010
comment
@nakiya: Оптимизацию возвращаемого значения можно найти во многих более продвинутых книгах по C++. Я бы рискнул сказать, что программы, в которых конструкторы копирования имеют побочные эффекты, скорее всего, содержат ошибки независимо от того, действует ли RVO или нет, потому что я думаю, что это очень плохая идея. - person David Thornley; 11.10.2010
comment
@nakiya: многие вещи в C ++ могут вызывать ошибки, если разработчик о них не знает. Но если вы напишете свой конструктор копирования так, чтобы он имел смысл, то есть он создает копию и ничего больше, тогда он просто работает с RVO и без него. - person jalf; 11.10.2010

Как сказано в других ответах, компилятору разрешено оптимизировать даже нетривиальные конструкторы копирования и операторы присваивания.

12.8.15

При соблюдении определенных критериев реализации разрешается пропускать конструкцию копирования объекта класса, даже если конструктор копирования и/или деструктор объекта имеют побочные эффекты. В таких случаях реализация рассматривает источник и цель пропущенной операции копирования просто как два разных способа обращения к одному и тому же объекту, и уничтожение этого объекта происходит в более позднее время, когда два объекта были бы уничтожены без оптимизация. Это исключение операций копирования разрешено в следующих случаях (которые могут быть объединены для устранения множественных копий):

— в операторе return в функции с возвращаемым типом класса, когда выражение является именем энергонезависимого автоматического объекта с тем же типом cv-unqualified, что и возвращаемый тип функции, операцию копирования можно опустить, построив автоматический объект непосредственно в возвращаемое значение функции

- когда временный объект класса, который не был привязан к ссылке (12.2), будет скопирован в объект класса с тем же типом cv-unqualified, операцию копирования можно опустить, создав временный объект непосредственно в цель опущенного копировать

person DerKuchen    schedule 11.10.2010
comment
+1 за цитату, пожалуйста, также дайте ссылку на копию стандарта для проверки - person Matt Joiner; 12.10.2010
comment
@Matt: Это сделало бы ссылку на ссылку. В научных статьях и книгах обычно упоминается только BibTex или название какой-либо книги, без упоминания Amazon или ISO, где вы можете получить эти названия. В любом случае, для вашего удобства последняя версия стандарта находится в свободном доступе на open-std.org. - person Sebastian Mach; 29.09.2011
comment
В современную эпоху WWW я ожидал не меньше, чем гиперссылку, указывающую прямо на этот абзац. В мою защиту автор этого ответа даже не указывает, из какого стандарта, года или версии он это взял. - person Matt Joiner; 29.09.2011
comment
@MattJoiner, ты можешь ожидать чего угодно, но ты этого не получишь. В Интернете нет (законных) копий стандарта в формате HTML, это защищенный авторским правом документ, официально доступный только в бумажной форме или в формате PDF, поэтому было бы сложно и/или непослушно ссылаться на конкретный абзац в удобной форме. Вот источник LaTeX для этого абзаца, кратко до того, как был опубликован окончательный стандарт, но читать LaTeX не очень удобно. - person Jonathan Wakely; 26.06.2012
comment
even non trivial copy constructors and assignment operators zoom: assignment Нигде в этой цитате не упоминается оператор присваивания копирования. У вас есть фактическая ссылка на это? Спойлер: я не думаю, что вы найдете его, потому что ответ здесь: Почему RVO не происходит для оператора присваивания? т. е. по совершенно очевидным причинам [N]RVO не применимо к копированию-назначению. - person underscore_d; 13.07.2016

Дайте определение «неправильно». Язык C++ явно допускает такую ​​оптимизацию, даже если она доступна для наблюдения. Если поведение вашей программы зависит от конкретной реализации, то, к сожалению, вы используете не ISO C++, а какой-то диалект.

person Helmut Grohne    schedule 11.10.2010