|
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
|
|||||||||||
Странный порядок вызова конструкторов и передача временного обьекта в функцию в качестве неконстантной ссылки09.07.2017, 22:18. Показов 2642. Ответов 25
Метки нет (Все метки)
Есть код
У меня по нему несколько вопросов: 1. Конструкция foo() = 5 генерирует временный объект, а временный обьект в функцию по ссылке можно передавать только если эта ссылка константная. Каким образом функция bar в данном коде принимает ссылку на временный обьект? Ведь ссылка то не константная! 2. Вызов конструктора, который принимает (int). Как такое происходит? Я бы понял если было бы написано foo f = 5; но тут написанно foo() = 5, то есть синтаксис, в котором вызывается конструктор по умолчанию. По идее этот код не должен компилироваться, потому что ведь выражение парсится справа на лево. То есть левосторонний объект foo() ещё не создан, а int конструктор почему то вызывается так, как будто этот объект создан(иначе в результате конструктор по умолчанию был бы вызван первым) 3. Порядок вызова конструкторов. int ctor default assign by ref Итого сработало 3 конструктора: Тот что сработал первым думаю станет понятно почему если поможете разобраться с вопросом из п.2 Тот что сработал вторым - полагаю это при создании временного foo() который слева от 5 Но каким боком здесь оператор копирования присваиванием? Ведь он вызывается тогда, когда уже объект перемешается по ссылке в функцию. То есть данный конструктор не должен быть вызван т.к объект мы не создаём а передаём ссылку в функцию, но даже если по каким то соображениям нужно бы было вызвать конструктор, то уж точно не копирования с присваиванием т.к для передачу в функции используются конструкторы с круглыми скобками. Надеюсь что кто нибудь поможет разобраться с этим... Добавлено через 11 минут А вот в этом коде создаётся 2 обьекта но вызывается три конструктора! В чем дело? ![]()
0
|
|||||||||||
| 09.07.2017, 22:18 | |
|
Ответы с готовыми решениями:
25
Порядок вызова конструкторов
|
|
Заблокирован
|
||
| 09.07.2017, 22:20 | ||
foo() = 5, foo(int) вызывается для 5, конструктор без аргументов вызывается для foo() а потом вызывается оператор присваивания.
1
|
||
|
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
|||||||||||||||||
| 09.07.2017, 22:23 | |||||||||||||||||
которому присваивается циферка 5. класс не умеет присваивать циферки, зато умеет с них строится. поэтому циферка 5 приводится к типу класса:
который возвращает обычную ссылку, которую принимает bar
1
|
|||||||||||||||||
|
Заблокирован
|
|
| 09.07.2017, 22:23 | |
|
1
|
|
|
Вездепух
12931 / 6799 / 1820
Регистрация: 18.10.2014
Сообщений: 17,210
|
|||||
| 09.07.2017, 22:27 | |||||
Сообщение было отмечено Undisputed как решение
РешениеЕсть правило "rvalue по обычной ссылке можно передавать только если эта ссылка константная". Например, выражение foo() порождает rvalue и передать его результат в функцию по обычной ссылке можно было бы только если бы эта ссылка была константной. "Временные объекты" часто попадают в это правило потому, что выражения, формирующие временные объекты, сами по себе обычно являются rvalue. Например, foo() - это rvalue.Но у вас в коде в bar() передается не foo(), а foo() = 5. Результат foo() = 5 - это результат оператора присваивания. А он у вас уже возвращает lvalue типа int. Так как это lvalue, его можно передавать по неконстатной ссылке. А то, что это lvalue ссылается на временный объект никакой роли не играет.foo() = foo(5). Вот в правой части вы и видите ваш конструктор, который принимает (int).Оператора присваивания для правой части типа int у вас в коде нет вообще. Поэтому этот код компилируется через преобразование правой части к foo при помощи вашего же конструктора преобразования.foo() = 5. Вот он и вызывается!
2
|
|||||
|
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
||||||||
| 09.07.2017, 22:28 | ||||||||
0
|
||||||||
|
Заблокирован
|
|
| 09.07.2017, 22:29 | |
|
0
|
|
|
Вездепух
12931 / 6799 / 1820
Регистрация: 18.10.2014
Сообщений: 17,210
|
|||
| 09.07.2017, 22:41 | |||
foo.Никто не запрещает вам доступаться к временному объекту, как к lvalue, если вы сформируете соответствующее выражение, обеспечивающее такой доступ. Сама суть понятия "объект" в С++ ("область в хранилище") говорит, что к объекту, при желании, всегда можно получить lvalue-доступ (разве что битовые поля являются исключением).
3
|
|||
|
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
|
||||||
| 09.07.2017, 22:51 [ТС] | ||||||
|
Всем большое спасибо за ответы, вроде разобрался с вашей помощью!
Но с передачей в функцию аргумента не до конца понял, это похоже на обман компилятора. Несмотря на то что operator = возвращает ссылку на foo и это полностью соответствует сигнатуре функции bar, тем не менее, он все же rvalue, и если фактически передать тот же самый объект который формируется как rvalue, но только иным образом, то ведь не скомпилируется код!
0
|
||||||
|
Заблокирован
|
||
| 09.07.2017, 23:03 | ||
|
Результат вызова функции, возвращающей lvalue-ссылку является lvalue. operator=() возвращае lvalue-ссылку. Добавлено через 5 минут Если хочешь запретить вызывать operator=() у временных объектов, добавь к нему нужный ref qualifier.
1
|
||
|
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
|||
| 09.07.2017, 23:04 | |||
foo() - это prvalue.выражение, которое даёт доступ к "чисто pvalue", ну или к "реально временному объекту", если попроще. а pvalue к обычной ссылке не биндится. только к константной.
1
|
|||
|
Вездепух
12931 / 6799 / 1820
Регистрация: 18.10.2014
Сообщений: 17,210
|
||
| 09.07.2017, 23:06 | ||
|
В общем, идея заключается в том, что привязать обычную неконстантную ссылку к временному объекту можно, но для этого надо сознательно сделать дополнительные телодвижения. Вот вы их и сделали. Правда, бессознательно.
1
|
||
|
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
|
|
| 09.07.2017, 23:14 [ТС] | |
|
TheCalligrapher,
Ну по стандарту константная ссылка на временный объект продлевает время жизни этого объекта до тех пор, пока жива эта ссылка. Поэтому если явно не стрелять себе в ногу манипулируя адресами думаю проблем быть не должно т.к есть гарантии, что такой объект можно читать безопасно. Но про неконстантные ссылки на временные объекты все что я слышал это UB
0
|
|
|
Вездепух
12931 / 6799 / 1820
Регистрация: 18.10.2014
Сообщений: 17,210
|
||||
| 09.07.2017, 23:24 | ||||
|
1
|
||||
|
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
||
| 09.07.2017, 23:25 | ||
|
способ, который вы использовали в самом нулевом посте - вполне себе законный. что касается слухов, которые вы там слышали: вероятно имелось ввиду, что нельзя срисовать обычную ссылку с rvalue. вот это - не по стандарту. православные компиляторы (gcc например) просто откажутся такое компилировать. вижуал-студийный компилятор скушает. но сделает предупреждение: "задействовано нестандартное расширение компилятора". что касается UB - все законно. вам в любом случае нужно иметь ввиду, временный объект сдохнет сразу же, как только закончится породившее его выражение. если только он не был прибинден к константной ссылке в той же области видимости, что и породившее его выражение.
1
|
||
|
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
|
||||||
| 09.07.2017, 23:34 [ТС] | ||||||
|
TheCalligrapher,
А вот это разве не UB? Создание не константной ссылки на временный объект
0
|
||||||
|
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
|||||||
| 10.07.2017, 01:39 | |||||||
|
у вас там создается временная константная ссылка, которая биндит временный объект. и успешно продливает его жизнь. вот только, когда все выражение завершается, завершается время жизни и этой самой временной константной ссылки. она дохнет. дохнет и связанный с нею временный объект. не константная ссылка по итогу смотрит на трупик. Добавлено через 2 минуты к тому же, вот здесь:
который изначально был рожден константным. а это уже - есть UB нельзя снимать константность с объектов, рожденных константными.
1
|
|||||||
|
Вездепух
12931 / 6799 / 1820
Регистрация: 18.10.2014
Сообщений: 17,210
|
||||||||
| 10.07.2017, 01:48 | ||||||||
|
Аналогичный пример
Добавлено через 2 минуты
3
|
||||||||
|
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
|
|
| 18.02.2018, 02:09 | |
|
0
|
|
|
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
|||||||
| 18.02.2018, 13:55 | |||||||
|
что такое "попытка модификации"? допустим у класса есть не константный метод. значит, теоретически, внутри этого метода может быть модификация объекта. вопрос: 1. запуск такого метода для объекта рожденного константным - есть UB? 2. или операции непосредственно записи в память объекта - есть UB? формально - правильный ответ 2. но на практике - правильный ответ 1. копилятор вправе закладываться на неизменность состояния объекта рожденного константным. что произойдет при запуске неконстантного метода - хз. он не телепат, но будет считать что объект не изменился. и вот здесь на практике мы находимся в ситуации, когда нам никто уже ничего не гарантирует - UB
0
|
|||||||
| 18.02.2018, 13:55 | |
|
Помогаю со студенческими работами здесь
20
Порядок вызова конструкторов/деструкторов Классы, наследование, порядок вызова конструкторов Порядок вызова конструкторов при множественном наследовании Порядок вызова конструкторов при присваивании объектов одного класса Передача временного массива в качестве параметра функции Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
|
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
|
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11
— это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
|
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11
Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
|
|
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
|
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/
O1rJuneU_ls
https:/ / vkvideo. ru/ video-115721503_456239114
|
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ВВЕДЕНИЕ
Введу сокращения:
аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
|
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi
ветка по-частям.
коммит Create переделка под биомассу. txt
вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
|