|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
Есть такой код: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
Непонятно, почему нельзя заинтинить ссылку? Возвращается копия с shared_ptr же? Т.е. одно дело, если бы я возвращал временный объект. Или компилятор этого не знает и боится? И мне до конца непонятен смысл константных ссылок, что происходит в третьей строке, и какие есть подводные камни и ограничения? -------- Забегая немного назад, изначально вариант метода был такой: Код: plaintext 1.
но мне понадобилось иногда возвращать weak_ptr::lock(), а оно не хочет возвращать ссылку. Опять не совсем понятно, почему? lock возвращает shared_ptr. Я немного пострадал по поводу оптимальности, убрал ссылку из возвращаемого результата, и тут выяснилось, что таким "указателем" нельзя инитить ссылки :( ... |
|||
:
Нравится:
Не нравится:
|
|||
18.12.2019, 10:06 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
CEMb Непонятно, почему нельзя заинтинить ссылку? Возвращается копия с shared_ptr же? Т.е. одно дело, если бы я возвращал временный объект. Твоя копия указателя - это тут и есть временный объект. Если ссылка будет не константной, то пропадут изменения в этом не константном временном объекте. Компилятор считает это не корректным. Во второй строчке может сработать Return Value Optimization. И временного объекта не будет. Про третью строчку, у меня есть обоснованное мнение, но я промолчу. Вроде так. :) ... |
|||
:
Нравится:
Не нравится:
|
|||
18.12.2019, 12:22 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
CEMb но мне понадобилось иногда возвращать weak_ptr::lock(), а оно не хочет возвращать ссылку. Опять не совсем понятно, почему? lock возвращает shared_ptr. weak_ptr реализует слабую связь. Что бы с объектом, на который ссылается weak_ptr, можно было бы поработать - эту связь нужно временно превратить в сильную. Поэтому lock возвращает shared_ptr. CEMb Я немного пострадал по поводу оптимальности, убрал ссылку из возвращаемого результата, и тут выяснилось, что таким "указателем" нельзя инитить ссылки :( Не очень понятно чего ты добиться хочешь. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.12.2019, 12:27 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
CEMb Забегая немного назад, изначально вариант метода был такой: Код: plaintext 1.
но мне понадобилось иногда возвращать weak_ptr::lock(), а оно не хочет возвращать ссылку. Опять не совсем понятно, почему? lock возвращает shared_ptr. Небольшое дополнение. Если ты сделаешь как ты хочешь, а хочешь ты, видимо, так: Код: plaintext 1.
То получится, что ты тут возвращаешь адрес (в виде ссылки) на временный объект, который лежит на стеке. И так тоже нельзя. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.12.2019, 19:01 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
petrav Твоя копия указателя - это тут и есть временный объект. petrav Про третью строчку, у меня есть обоснованное мнение, но я промолчу. petrav То получится, что ты тут возвращаешь адрес (в виде ссылки) на временный объект, который лежит на стеке. И так тоже нельзя. - в объекте класса А есть 2 shared_ptr - функция GetPtr в зависимости от условий возвращала один из них, как ссылку. Возвращать ссылку - это хорошо. Возвращать shared_ptr в моём случае - не очень хорошо, потому что ситуация "поработал и забыл", достаточно ссылки. - условия для решения, что возвращать, передавались параметрами в GetPtr. - потом обращение к объекту класса А стало итерационным, и по архитектурной задумке один из shared_ptr должен был стать текущим, его должен был возвращать GetPtr(без параметров) Т.е. кто-то внутри должен на него указывать(далее shared_ptr-ов может быть больше двух, они могут быть в векторе, перемешиваться, и так далее, поэтому просто индекс в качестве указующего не подойдёт). - можно было бы взять ещё один shared_ptr и использовать его в качестве посредника, но, во-первых, как-то не совсем хорошо, во-вторых, может быть ситуация, когда текущий из shared_ptr-ов обнулился, а посредник будет держать объект живым, а вот weak_ptr может определить, что объекта уже нет (expired), но его lock - временный объект, вернуть ссылку на него нельзя. ps: есть ещё вариант: возвращать просто указатель, потому что после GetPtr всё равно надо на null проверять. ... |
|||
:
Нравится:
Не нравится:
|
|||
19.12.2019, 05:47 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
CEMb ps: есть ещё вариант: возвращать просто указатель, потому что после GetPtr всё равно надо на null проверять. Смотри: Код: plaintext 1. 2. 3. 4.
На момент завершения работы этой функции локальный временный shared_ptr уже разрушен. Связь снова стала слабой. И когда ты воспользуешься возвращённым указателем -- объект из динамической памяти может быть уже удалён в другом потоке. И у тебя на руках сырой указатель в пустоту, и ты лезешь по нему. Даже в однопоточном приложении можно получить такой эффект. Особенно в GUI приложении. ... |
|||
:
Нравится:
Не нравится:
|
|||
19.12.2019, 09:54 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
CEMb - можно было бы взять ещё один shared_ptr и использовать его в качестве посредника, но, во-первых, как-то не совсем хорошо, во-вторых, может быть ситуация, когда текущий из shared_ptr-ов обнулился, а посредник будет держать объект живым, а вот weak_ptr может определить, что объекта уже нет (expired), но его lock - временный объект, вернуть ссылку на него нельзя. Я так понял тебе weak_ptr<> вообще не нужен. Код: 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. 32. 33.
... |
|||
:
Нравится:
Не нравится:
|
|||
19.12.2019, 10:54 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
CEMb ps: есть ещё вариант: возвращать просто указатель, потому что после GetPtr всё равно надо на null проверять. если ptr требуется на null проверять, значит вы делаете что-то не то а RAII тут точно нельзя применить? RAII стоит впереди умных указателей ... |
|||
:
Нравится:
Не нравится:
|
|||
19.12.2019, 12:14 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
Код: plaintext 1. 2. 3. 4. 5. 6. 7.
... |
|||
:
Нравится:
Не нравится:
|
|||
19.12.2019, 12:23 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#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. 32. 33. 34. 35. 36.
... |
|||
:
Нравится:
Не нравится:
|
|||
19.12.2019, 12:41 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
полудух, Хороши твои классы, прямо созданы для memory leak и падение приложения. А повторное использование прямо какое, а! ... |
|||
:
Нравится:
Не нравится:
|
|||
19.12.2019, 13:19 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
они не мои, а Страуструпа и где у него leak? ... |
|||
:
Нравится:
Не нравится:
|
|||
19.12.2019, 16:10 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
второй Страуса, первый не помню ... |
|||
:
Нравится:
Не нравится:
|
|||
19.12.2019, 16:10 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
petrav На момент завершения работы этой функции локальный временный shared_ptr уже разрушен. Связь снова стала слабой. И когда ты воспользуешься возвращённым указателем -- объект из динамической памяти может быть уже удалён в другом потоке. И у тебя на руках сырой указатель в пустоту, и ты лезешь по нему. petrav curr = 1; полудух если ptr требуется на null проверять, значит вы делаете что-то не то а RAII тут точно нельзя применить? ------- таким образом, получается, оптимальнее всего делать так: 1. weak_ptr внутри класса на один из shared_ptr 2. возвращаем shared_ptr, а не ссылку на него (но жаба душит всё ещё) ... |
|||
:
Нравится:
Не нравится:
|
|||
20.12.2019, 05:56 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
CEMb таким образом, получается, оптимальнее всего делать так: 1. weak_ptr внутри класса на один из shared_ptr 2. возвращаем shared_ptr, а не ссылку на него (но жаба душит всё ещё) Так заботишься о производительности что и объект не вернуть? :) Возможно там и не будет собственно возвращения временного объекта. Возможно сработает Return Value Optimization. Но там будет вещь на порядок хуже. Там будет атомарная инкрементация счётчика, с барьерами памяти и всем прочим. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.12.2019, 12:03 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
полудух они не мои, а Страуструпа и где у него leak? Во втором исходнике, который ты привёл, после операции копирования ScopedPtr будет сначала утечка памяти, а потом будет падение приложения. Тот первый исходник, который ты привёл, тоже кривой. Из-за неоправданной операции разыменования интеллектуального указателя. Кроме того, концепция была не по делу применена. ИМХО. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.12.2019, 18:16 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#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. 32. 33. 34. 35. 36.
petrav полудух они не мои, а Страуструпа и где у него leak? Во втором исходнике, который ты привёл, после операции копирования ScopedPtr будет сначала утечка памяти, а потом будет падение приложения. copy, в смысле "ScopedPtr a = e;" ? ... |
|||
:
Нравится:
Не нравится:
|
|||
20.12.2019, 20:10 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
полудух copy, в смысле "ScopedPtr a = e;" ? Да. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.12.2019, 20:13 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
а почему просто не создать новый ScopedPtr a = new Entity? anyway, умные указатели там всё таки нужны, они тоже часть RAII. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.12.2019, 20:20 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
полудух а почему просто не создать новый ScopedPtr a = new Entity? А если я хочу копию указателя на тот же объект? Может я случайно написал копирование. Не важно. Я не против разработки велосипедов, они помогают понять суть вещей. Но я против заведомого говнокода. В ваших примерах достаточно было заблокировать конструктор и оператор копирования. И всё было бы приемлимо. полудух anyway, умные указатели там всё таки нужны, они тоже часть RAII. Твой ScopedPtr -- это и есть умный указатель и реализация RAII. Просто кривая реализация. И вредная для новичков, хотя и концептуально полезная. Но недостаточно. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.12.2019, 20:29 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
я про это и говорю - пример у меня не полный (каюсь), в полном таки есть умные указатели. petrav В ваших примерах достаточно было заблокировать конструктор зачем, там же make_shared? ... |
|||
:
Нравится:
Не нравится:
|
|||
20.12.2019, 21:32 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
petrav Твой ScopedPtr -- это и есть умный указатель и реализация RAII. Просто кривая реализация. И вредная для новичков, хотя и концептуально полезная. Но недостаточно. Для Полудуха: читайте про rule of three, ну и заодно про rule of five https://en.wikipedia.org/wiki/Rule_of_three_(C _programming) ... |
|||
:
Нравится:
Не нравится:
|
|||
21.12.2019, 02:39 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
Anatoly Moskovsky, почитал, спасибо ... |
|||
:
Нравится:
Не нравится:
|
|||
21.12.2019, 11:29 |
|
Немножко про shared_ptr
|
|||
---|---|---|---|
#18+
CEMb, Пишут же тебе всё человечьим голосом: C2440, A non-const reference may only be bound to an lvalue ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2019, 00:11 |
|
|
start [/forum/topic.php?fid=57&msg=39905257&tid=2017497]: |
0ms |
get settings: |
10ms |
get forum list: |
12ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
30ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
56ms |
get tp. blocked users: |
1ms |
others: | 265ms |
total: | 390ms |
0 / 0 |