Russian Qt Forum
Ноябрь 23, 2024, 04:16 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 [3]   Вниз
  Печать  
Автор Тема: Передача анонимных объектов по константн  (Прочитано 14810 раз)
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #30 : Декабрь 06, 2014, 00:39 »

Код
C++ (Qt)
MyClass GetA( void );
..
MyClass a = GetA();
Как Вы знаете здесь никакого копирования нет, вызывается 1 конструктор (извращения MSVC не в счет). Тем не менее также требуется конструктор копирования

Здесь есть копирование.
Однако срабатывает стандартная оптимизация RVO, и копирующий конструктор становится не наблюдаем.

Современные компиляторы (в том числе msvc) применяют её даже для режима "без оптимизации".

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

Примечание: msvc (по крайней мере 2008 компилятор точно, новые не проверял) допускает отсутствие копирующего конструктора, когда заранее знает, что оптимизирует его. Но это - расширение от компилятора.
« Последнее редактирование: Декабрь 07, 2014, 08:35 от _Bers » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #31 : Декабрь 06, 2014, 10:01 »

Здесь есть копирование.
Однако срабатывает стандартная оптимизация NRVO, и копирующий конструктор становится не наблюдаем.
Что значит "не наблюдаем"?  Улыбающийся Он просто не вызывается.

Современные компиляторы (в том числе msvc) применяют её даже для режима "без оптимизации".
MSVC 2012 в режиме Debug вызывает конструктор копирования (в этом году проверял)
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #32 : Декабрь 07, 2014, 08:16 »

Что значит "не наблюдаем"?  Улыбающийся Он просто не вызывается.

Он оптимизирован.

Компилятор догадывается, что результат выражения
Код:
auto obj1 = foo(); //return some(param);

Будет аналогичен выражению:

Код:
some obj1(param);

Выпиливает создание временного объекта.
А для результирующего объекта заменяет вызов копирующего конструктора на explicit ctor

При этом, допустим мы почему то захотели что бы в копирующем конструкторе были эффекты. Например запрос в БД.
А в конструкторе с параметрами таких эффектов нет.

В этом случае получается, что компилятор выполняя такую оптимизацию нарушает ожидаемую нами логику: мы рассчитывали на запрос в БД, но после оптимизации его не случилось.

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

Однако, следование этому правилу накорню обламывает множество важных оптимизаций связанных с копированием объектов.

Раньше компиляторы умели RVO/NRVO, но в большинстве случаев они оказывались недопустимыми из-за возможных эффектов.
Поэтому, стандарт их узаконил.

С этого момента, компиляторы были обязаны поддерживать и использовать оптимизации RVO/NRVO.
в частности, выражение:

Код:
auto obj = some();
компилятор обязан оптимизировать до:
Код:
some obj;

Код:
auto obj = some(param);
компилятор обязан оптимизировать до:
Код:
some obj(param);


Для копирующих конструкторов была сделала оговорка.
Я точно не помню как она звучит в оригинале.

Я запомнил её в своём весьма вольном переводе:
нельзя закладываться на то, что копирующий конструктор будет наблюдаемый.

Всегда нужно иметь ввиду, что компилятор может выпилить копирования невзирая на содержимое копирующего конструктора.



Поэтому эффекты в конструкторе копирования - это ill-formed.
В хорошей программе они не допустимы.




(хотя функции с эффектами, это строго говоря само по себе ill-formed.
Ответ на вопрос "почему?" можно найти в книжках аля "Идеальный код" Макконелла)


MSVC 2012 в режиме Debug вызывает конструктор копирования (в этом году проверял)


msvc2012, тулсет: штатный из коробки, а так же ноябрьский. В дебаге оптимизирует копирование временных объектов.
msvc2013, тулсет: штатный из коробки, а так же ноябрьский. В дебаге оптимизирует копирование временных объектов.

гцц
http://rextester.com/XUAMR22459

шланг
http://rextester.com/IOSR10427

2013 студия, ноябрь
http://rextester.com/BCN9840

2012 к сожалению не могу продемонстрировать на онлайн компиляторе.
Однако результат точно такой же. Я лично долбался с ним, пытаясь найти способ, как заставить компилятор не оптимизировать. Не нашел.
« Последнее редактирование: Декабрь 07, 2014, 08:54 от _Bers » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #33 : Декабрь 07, 2014, 10:01 »

msvc2012, тулсет: штатный из коробки, а так же ноябрьский. В дебаге оптимизирует копирование временных объектов.
msvc2013, тулсет: штатный из коробки, а так же ноябрьский. В дебаге оптимизирует копирование временных объектов.
Да бог с ним, в MSVC может быть что угодно. Проблема в том что "нормальные" компиляторы требуют конструктор копирования, хотя и не используют его. Это вызывает неудобства если класс планируется как неперемещаемый. Можно ли сказать что в С++ 11 эта проблема решена?

Спасибо
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #34 : Декабрь 07, 2014, 14:43 »

Можно ли сказать что в С++ 11 эта проблема решена?

с++03 узаконили RVO/NRVO
c++11 вытащили контроль за r-value на уровень пользователя.

Однако принципиально ничего не изменилось.

Я предоставил ссылки выше, которые иллюстрируют, что r-value конструкторы так же не наблюдаемы.
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #35 : Декабрь 07, 2014, 14:47 »

Да бог с ним, в MSVC может быть что угодно.

Совершенно напрасно так думаете. msvc2012 полностью соответствует стандарту.

Он позволяет по дефолту собственные расширения, которые значительно облегчают жизнь для не_кросс_платформы.

Но при этом, если код соответствует стандарту - msvc его скомплиирует, и поведение будет ожидаемым. Инфа 100%
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #36 : Декабрь 08, 2014, 12:02 »

Совершенно напрасно так думаете. msvc2012 полностью соответствует стандарту.
Не "думаю", а "на горьком опыте" Улыбающийся Ладно, не хочу тратить Ваше и свое время на "уличение MSVC", лучше вот что спрошу:

Есть класс копирование которого нежелательно. Напр у меня контейнер возможно содержащий гигабайты данных. Хорошо, делаем конструктор и оператор = private. Но надо распараллелить расчеты, поэтому каждая нитка должна иметь свой такой контейнер. Приходится отказаться от private. Конечно всегда можно делать указатель, но это не очень удобно. Как грамотно разрулить эту ситуацию?

Спасибо
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #37 : Декабрь 08, 2014, 12:12 »

Реализовать этот контейнер с implicit shared.
Записан
Страниц: 1 2 [3]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.202 секунд. Запросов: 23.