|
Что происходит ?
|
|||
---|---|---|---|
#18+
Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.
... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 13:29 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
Код: plaintext 1.
возврат копии структуры по значению. Возможно при использовании оптимизации компилятор применит RVO и сократит ряд копирований/разружений. В этом случае лучше определить перемещающий конструктор и использовать std::move, чтобы гарантировано избежать подобных неоднозначностей. В данном случае возвращаемое значение (rvalue) улетает в никуда Код: plaintext 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 13:52 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
Cerebrum Код: plaintext 1.
возврат копии структуры по значению. Возможно при использовании оптимизации компилятор применит RVO и сократит ряд копирований/разружений. В этом случае лучше определить перемещающий конструктор и использовать std::move, чтобы гарантировано избежать подобных неоднозначностей. В данном случае возвращаемое значение (rvalue) улетает в никуда Код: plaintext 1.
T t = std::move(getT()); ? ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 14:03 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
--В данном случае возвращаемое значение (rvalue) улетает в никуда В никуда это не ответ Что происходит ? ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 14:04 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
semen.s.semen--В данном случае возвращаемое значение (rvalue) улетает в никуда В никуда это не ответ Что происходит ? getT возвращает значение которое никто не принимает, следовательно тут будет все зависеть от компилятора Если сборка производится с оптимизирующими флагами и внутри getT никто не выделяет память из кучи, то компилятор скорее всего вообще удалит данный вызов, как мусорный и не меняющий саму суть кода. В debug режиме компилятор может создать rvalue копию значения, которая будет разрушена при выходе из области видимости, т.е. }. Но поскольку обратится к ней нет никакой возможности, debug компилятор, может также выкинуть эту инструкцию, просто вызовет getT, но возвращаемое значение соптимизирует. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 14:10 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
std::move это страшная покрытая мраком мгла - которая ничуть не более чем каст Реально есть память А, есть память B и дальше мы каким то образом переносим данные из одной части в другую Вот у нас стек 1 <----- зашли в getT() 2 выделили память под T; 3 <------ вышли из getT(); Я так понимаю, что при определенных настройках компилятора - мы заиспользуем прямо ту память которая на стеке была зерезервирована в точке 2 Однако при выходе из метода ее уже может не существовать (все таки стек) Вот и хочется понять экспертизу данного поведения При каких ключиках и настройках (или других факторах) мы получим адрес ровной той памяти что выделилась на стеке внутри метода - а при каких на стеке создадут копию и как то переместят туда ранее созданное в методе добро (как это будут делать при помощи std::move или copy конструктора) - дело десятое. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 14:18 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
semen.s.semenВот и хочется понять экспертизу данного поведения Ну так --save-temps в руки и смотри на порождаемый ассемблер до просветления. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 14:23 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
semen.s.semenstd::move это страшная покрытая мраком мгла - которая ничуть не более чем каст Реально есть память А, есть память B и дальше мы каким то образом переносим данные из одной части в другую Вот у нас стек 1 <----- зашли в getT() 2 выделили память под T; 3 <------ вышли из getT(); ... Может так быть: 1 выделили память под T; 2 <----- зашли в getT() 3 <------ вышли из getT(); Со стеком полный порядок. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 14:40 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakovsemen.s.semenВот и хочется понять экспертизу данного поведения Ну так --save-temps в руки и смотри на порождаемый ассемблер до просветления. Ох уж эти RTFM и поди погугли эксперты :) Хочется информации от умных людей ) ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 15:06 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
Cerebrum, спасибо извиняюсь если был грубоват - характер. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 15:08 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
Копирование происходит в данном случае Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
Выводит Код: plaintext 1.
MSVC 2017 ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 15:14 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
Dima Tsemen.s.semenstd::move это страшная покрытая мраком мгла - которая ничуть не более чем каст Реально есть память А, есть память B и дальше мы каким то образом переносим данные из одной части в другую Вот у нас стек 1 <----- зашли в getT() 2 выделили память под T; 3 <------ вышли из getT(); ... Может так быть: 1 выделили память под T; 2 <----- зашли в getT() 3 <------ вышли из getT(); Со стеком полный порядок. Теоретически таких T внутри метода может быть масса Заранее выделить в стеке не получится ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 15:28 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
semen.s.semenDima Tпропущено... Может так быть: 1 выделили память под T; 2 <----- зашли в getT() 3 <------ вышли из getT(); Со стеком полный порядок. Теоретически таких T внутри метода может быть масса Заранее выделить в стеке не получится Почему? ИМХО это просто шаманство на уровне компиляции, компилятор видит весь код и в разных случаях один и тот же код getT() скомпилирует по-разному. Своими словами мне сложно объяснить, в этой книге неплохо описаны принципы работы std::move ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 15:48 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
Да причем тут вообще std::move ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 15:58 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
Dima TСвоими словами мне сложно объяснить Это говорит об отсутствии четкого и ясного понимания и экспертизы ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 15:59 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
semen.s.semenDima TСвоими словами мне сложно объяснить Это говорит об отсутствии четкого и ясного понимания и экспертизы Я с std::move не разбирался, как понял он и так работает в stl. А данном коде просто копирование происходит. Может код понятнее будет если заменить T на int. Разницы никакой. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 16:10 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31.
... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 17:32 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31.
... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 17:33 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
semen.s.semen, Вызывающий код выделяет память в стеке под возвращаемое значение и передает его адрес в функцию вместе с аргументами (адрес не всегда нужно передавать явно, например если память выделить на верхушке стека, то вызывающая функция может адрес рассчитать; это все зависит от реализации). Вызванная функция создает объект в этой памяти. Вызывающий код пользуется этим объектом, потом вызывает для него деструктор и освобождает память - при выходе из области видимости. Если функция вызывается без присвоения в переменную, то происходит все тоже самое, только переменная не видна программисту и освобождается после вызова. Все вышеописанное происходит в любом случае даже без оптимизаций. Есть еще оптимизация RVO. Если внутри функции создается переменная, которая потом возвращается, то компилятор имеет право не создавать отдельную переменную и потом копировать ее в возвращаемое значение, а создать эту переменную сразу в памяти выделенной под возвращаемое значение. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 17:46 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
Поправка, то что я описал - это NRVO. А RVO работает на вызывающей стороне, когда возвращаемое значение создается в переменной куда присваивается, а не во временной с копированием в переменную. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 17:52 |
|
Что происходит ?
|
|||
---|---|---|---|
#18+
Anatoly Moskovskysemen.s.semen, Вызывающий код выделяет память в стеке под возвращаемое значение и передает его адрес в функцию вместе с аргументами (адрес не всегда нужно передавать явно, например если память выделить на верхушке стека, то вызывающая функция может адрес рассчитать; это все зависит от реализации). Вызванная функция создает объект в этой памяти. Вызывающий код пользуется этим объектом, потом вызывает для него деструктор и освобождает память - при выходе из области видимости. Если функция вызывается без присвоения в переменную, то происходит все тоже самое, только переменная не видна программисту и освобождается после вызова. Все вышеописанное происходит в любом случае даже без оптимизаций. Есть еще оптимизация RVO. Если внутри функции создается переменная, которая потом возвращается, то компилятор имеет право не создавать отдельную переменную и потом копировать ее в возвращаемое значение, а создать эту переменную сразу в памяти выделенной под возвращаемое значение. Спасибо за ясную экспертизу ... |
|||
:
Нравится:
Не нравится:
|
|||
29.03.2019, 17:53 |
|
|
start [/forum/topic.php?fid=57&msg=39793551&tid=2017645]: |
0ms |
get settings: |
8ms |
get forum list: |
13ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
33ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
51ms |
get tp. blocked users: |
1ms |
others: | 261ms |
total: | 386ms |
0 / 0 |