4173 / 2378 / 992
Регистрация: 07.02.2019
Сообщений: 6,212
1

Smart pointers

11.06.2019, 21:10. Показов 2632. Ответов 21

Уважаемые форумчане, такой вопрос: возможно ли как то в одном контейнере (в векторе например) хранить shared_ptr и указатели на lvalue. Полазил немного по инету и нашел std::enable_shared_from_this, но shared_from_this() для именованных объектов это UB или исключение бросается(C++17), weak_from_this() вроде работает, но опять же, как weak с shared объединить не знаю. На вопрос "И зачем тебе это понадобилось?" отвечу сразу: в познавательных целях, что бы в будущем, если по необходимости возникнет такая идея, был готовый ответ, например "Нет, не возможно, да и вообще за такое по клешням бить нужно".
1
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
11.06.2019, 21:10
Ответы с готовыми решениями:

Smart pointers + полиморфизм + делегирование. Ошибка компиляции
Доброго времени суток, уважаемые форумчане! Есть вопрос по поводу использования умных...

Smart Pointers: что такое и как с этим работать?
Народ, объясните мне что такое Smart Pointers, зачем нужны и как с ними работать?

Pointers
Здравствуйте, не могу понять принцип указателей, можете пожалуйста объяснить почему в этом коде ...

указатели (Pointers)
Напишите функцию, которая будет проверять, если подстрока "IPRE" можно найти в данной линии. ...

21
6737 / 4537 / 1838
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
11.06.2019, 21:22 2
Цитата Сообщение от zayats80888 Посмотреть сообщение
возможно ли как то в одном контейнере (в векторе например) хранить shared_ptr и указатели на lvalue.
Покажи, как ты себе это представляешь. А то непонятно
0
4173 / 2378 / 992
Регистрация: 07.02.2019
Сообщений: 6,212
11.06.2019, 21:30  [ТС] 3
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Покажи, как ты себе это представляешь. А то непонятно
Ну например, что бы вместо двух векторов в классе С был один:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class B
{
    //...
};
 
class C
{
    std::vector<B*> vb;
    std::vector<std::shared_ptr<B>> m_vb;
public:
    void add(std::shared_ptr<B> ptr)
    {
        m_vb.push_back(std::move(ptr));
        vb.push_back(&*m_vb.back());
    }
    void add(B& obj) { vb.push_back(&obj); }
    void add(B&& obj){ add(std::make_shared<B>(std::move(obj))); }
 
    using iterator = std::vector<B*>::iterator;
    iterator begin() { return vb.begin(); }
    iterator end() { return vb.end(); }
};
0
6737 / 4537 / 1838
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
11.06.2019, 21:35 4
Цитата Сообщение от zayats80888 Посмотреть сообщение
Ну например, что бы вместо двух векторов в классе С был один:
Один здесь не получится. Ты можешь положить в std::vector<B*>, но владеющий shared_ptr его удалит.
Два, как здесь, можно. В первом лежат указатели, второй держит shared_ptr, чтоб они не удалились
1
"C with Classes"
1485 / 1287 / 485
Регистрация: 16.08.2014
Сообщений: 5,415
Записей в блоге: 1
11.06.2019, 21:36 5
zayats80888, если проще ты хочешь в контейнере одного типа хранить объекты разных типов?
1
6737 / 4537 / 1838
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
11.06.2019, 21:38 6
Если класс наследуется от enable_shared, то shared_from_this вернёт null для не-shared_ptr

Добавлено через 1 минуту
Но, по-любому, метод очень мутный и лучше им не пользоваться
1
4173 / 2378 / 992
Регистрация: 07.02.2019
Сообщений: 6,212
11.06.2019, 21:39  [ТС] 7
Цитата Сообщение от _stanislav Посмотреть сообщение
если проще ты хочешь в контейнере одного типа хранить объекты разных типов?
Ну не буквально, я ж писал, хочу указатель на lvalue как нибудь засунуть в shared_ptr, только чтоб он его не удалял, как то счетчик увеличить например
0
6737 / 4537 / 1838
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
11.06.2019, 21:54 8
Цитата Сообщение от zayats80888 Посмотреть сообщение
только чтоб он его не удалял, как то счетчик увеличить например
Это никак, только хранить копию

Добавлено через 13 минут
Цитата Сообщение от zayats80888 Посмотреть сообщение
Ну например, что бы вместо двух векторов в классе С был один:
Кстати, в случае, когда тебе нужен массив указателей как на shared, так и на обычные объекты, то лучше сделать вот такой
C++
1
std::vector<std::pair<B *, std::shared_ptr<B>>> m_vb;
Добавлять - если B & , {&b, nullptr}, если shared_ptr - {sp.get(), sp}
Удалять потом, только те, у которых second == null
Тогда и enable_shared_from_this может не понадобится
1
Комп_Оратор)
Эксперт по математике/физике
8719 / 4426 / 598
Регистрация: 04.12.2011
Сообщений: 13,262
Записей в блоге: 16
11.06.2019, 22:36 9
Цитата Сообщение от zayats80888 Посмотреть сообщение
я ж писал, хочу указатель на lvalue как нибудь засунуть в shared_ptr, только чтоб он его не удалял, как то счетчик увеличить например
Непонятно. zayats80888, при чём lvalue? rvalue вообще могут не иметь адреса. Вы имеете ввиду передать в shared_ptr указатель которым он не владеет? Указатель на объект на стеке или указатель на объект внутри другого контейнера, или даже копию указателя внутри другого контейнера?? Непонятно при чём тут enable_shared_from_this?
Просто хочется понять суть вопроса.
0
4173 / 2378 / 992
Регистрация: 07.02.2019
Сообщений: 6,212
11.06.2019, 22:49  [ТС] 10
Цитата Сообщение от IGPIGP Посмотреть сообщение
Непонятно.
Процитированное вами это просто мысли вслух
Цитата Сообщение от IGPIGP Посмотреть сообщение
при чём lvalue?
Для примера из поста №3, скажем класс С это просто некий контейнер, в котором мы будем сортировать объекты класса B, не трогая их местоположения, и просто выводить на экран, это могут быть как именованные объекты на стеке, так и те которыми владеет сам контейнер(переданные как add(B(/* какой-то конструктор*/));
0
Комп_Оратор)
Эксперт по математике/физике
8719 / 4426 / 598
Регистрация: 04.12.2011
Сообщений: 13,262
Записей в блоге: 16
11.06.2019, 23:14 11
Цитата Сообщение от zayats80888 Посмотреть сообщение
это могут быть как именованные объекты на стеке, так и те которыми владеет сам контейнер
Во-о-от... Теперь понятнее. А то lvalue сбило с толку. Ведь объект в динамической памяти это тоже lvalue. Не верите? Разыменуйте указатель на такой объект и получите. Можно как-то так, например:
C++
1
2
 A pa = new A;
A &ra = *pa;//lvalue
Но не суть. Вернемся к
Цитата Сообщение от zayats80888 Посмотреть сообщение
это могут быть как именованные объекты на стеке, так и те которыми владеет сам контейнер
Мы же говорим о указателях. Они тоже объекты сами по себе. И ими владеет контейнер. Если это сырые указатели, то ни какого владения над объектами (целями указателей) не производится. Освобождать память нужно перед выходом контейнера из употребления (уничтожением). Но если создать вектор указателей, где объекты лежат то на стеке то в динамической памяти, то в статической... то потом нет ни какого разумного способа определить какой из них нужно освобождать, а какой нет. Это очень плохо (имхо).
shared_ptr созданы для того, как раз, чтобы работать с объектами в динамической памяти. Первый создаёт объект, а остальные работают с ним совместно. Создавать параллельно raw-pointers на его объекты, как долгожителей, это значит идти против самого себя. То же имхо. Хотя иногда такие указатели создаются, но неприменение к ним delete всегда на совести тех кто, это делает.
А что не так с сортировкой smart_pointer'ов? Это же не unique_ptr и копировать можно ведь?

Добавлено через 4 минуты
http://alenacpp.blogspot.com/2016/02/c.html
рекомендую блог этой дамы.
1
4173 / 2378 / 992
Регистрация: 07.02.2019
Сообщений: 6,212
11.06.2019, 23:18  [ТС] 12
Цитата Сообщение от IGPIGP Посмотреть сообщение
Ведь объект в динамической памяти это тоже lvalue.
Все верно, его в ту же топку.
Цитата Сообщение от IGPIGP Посмотреть сообщение
А что не так с сортировкой smart_pointer'ов?
Дык все ок, вопрос был не про это, а про возможность объединить в одном контейнере сырые и умные указатели на объекты одного класса, а про сортировку это я так, для примера, извиняйте если запутал. В принципе я уже получил на него ответ.

Добавлено через 1 минуту
Цитата Сообщение от IGPIGP Посмотреть сообщение
рекомендую блог этой дамы.
Спасибо.
0
Комп_Оратор)
Эксперт по математике/физике
8719 / 4426 / 598
Регистрация: 04.12.2011
Сообщений: 13,262
Записей в блоге: 16
11.06.2019, 23:23 13
Цитата Сообщение от zayats80888 Посмотреть сообщение
Дык все ок, вопрос был не про это, а про возможность объединить в одном контейнере сырые и умные указатели на объекты одного класса
_stanislav, задал совершенно твёрдый вопрос:
Цитата Сообщение от _stanislav Посмотреть сообщение
ты хочешь в контейнере одного типа хранить объекты разных типов?
И я присоединяюсь. Более того, я скажу, что этого сделать физически нельзя по совершенно очевидным причинам.
Цитата Сообщение от zayats80888 Посмотреть сообщение
это я так, для примера
Но ведь больше не было намёков на то, что вы имеете ввиду. Словом, смысл вопроса - самое трудное место в данном топике. И как я понял, я до сих пор его не понял. Но раз ответ вас устроил, значит всё Ок.
0
Эксперт С++
8410 / 4085 / 892
Регистрация: 15.11.2014
Сообщений: 9,176
11.06.2019, 23:25 14
Лучший ответ Сообщение было отмечено zayats80888 как решение

Решение

Цитата Сообщение от zayats80888 Посмотреть сообщение
Для примера из поста №3, скажем класс С это просто некий контейнер, в котором мы будем сортировать объекты класса B, не трогая их местоположения, и просто выводить на экран, это могут быть как именованные объекты на стеке, так и те которыми владеет сам контейнер(переданные как add(B(/* какой-то конструктор*/));
https://rextester.com/HQHLH24903

C++
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
#include <vector>
#include <memory>
 
struct B
{
    B(const int a):v(a)
    {
        std::cout << "B(): " << v << '\n';
    }
    
    ~B()
    {
        std::cout << "~B(): " << v << '\n';
    }
    
    int v;
};
 
class C
{
    std::vector< std::shared_ptr<B> > m_vb = {};
public:
    void add(std::shared_ptr<B> ptr)
    {
        std::cout << "share: " << ptr->v << '\n';
        this->m_vb.emplace_back(std::move(ptr));
    }
    void add(B& obj) 
    { 
        std::cout << "proxy: " << obj.v << '\n';
        this->m_vb.emplace_back(&obj, [](B*){});
    }
    void add(B&& obj)
    { 
        std::cout << "copy: " << obj.v << '\n';
        
        this->m_vb.emplace_back(
            std::make_shared<B>(std::move(obj))
        );
    }
    
    auto begin() { return this->m_vb.begin(); }
    auto end()   { return this->m_vb.end();   }    
};
 
int main()
{
    auto shared = std::make_shared<B>(11);
    
    B b{33};
    
    {
        C c;    
        c.add(b);
        c.add(B{66});
        c.add(shared);
        
        std::cout << "content: ";
        for(const auto& el: c)
            std::cout << el->v << ", ";
        std::cout << '\n';
        
    }
    std::cout << "\n======\n";
}
Код
B(): 11
B(): 33
proxy: 33
B(): 66
copy: 66
~B(): 66
share: 11
content: 33, 66, 11, 
~B(): 66

======
~B(): 33
~B(): 11
2
Комп_Оратор)
Эксперт по математике/физике
8719 / 4426 / 598
Регистрация: 04.12.2011
Сообщений: 13,262
Записей в блоге: 16
11.06.2019, 23:31 15
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
В первом лежат указатели, второй держит shared_ptr, чтоб они не удалились
Ну вернее оба они (контейнеры) "держат". Если представить, что некто проделитил пойнтер в "нативном" контейнере, то то в контейнере shared_ptr'ов в руках соответствующего объекта останется нечто неприличное. Это всё, что можно гарантировать, говоря об автоматике владения, в данном случае.
0
4173 / 2378 / 992
Регистрация: 07.02.2019
Сообщений: 6,212
11.06.2019, 23:37  [ТС] 16
hoggy, спасибо, если не трудно, объясните сточку 32, просто я в начинке smart пойнтеров не бум-бум, или ссылку дайте где почитать.

Добавлено через 3 минуты
Цитата Сообщение от hoggy Посмотреть сообщение
[](B*){}
а, это типо делитер такой?
0
6737 / 4537 / 1838
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
11.06.2019, 23:40 17
Цитата Сообщение от IGPIGP Посмотреть сообщение
Если представить, что некто проделитил пойнтер в "нативном" контейнере, то то в контейнере shared_ptr'ов в руках соответствующего объекта останется нечто неприличное.
Ну, во-первых, не надо давать "некту" их делитить. Во-вторых, я вроде где-то там же написал, как их различить. В-третьих - добавил, что я думаю о таком методе.

Добавлено через 1 минуту
Цитата Сообщение от zayats80888 Посмотреть сообщение
а, это типо делитер такой?
Да. В shared_ptr теперь можно передавать функцию удаления объекта, так же, как в unique_ptr

Добавлено через 1 минуту
[](B*){} - этот тупо ничего не удалит
1
Эксперт С++
8410 / 4085 / 892
Регистрация: 15.11.2014
Сообщений: 9,176
11.06.2019, 23:43 18
Цитата Сообщение от zayats80888 Посмотреть сообщение
объясните сточку 32
Цитата Сообщение от hoggy Посмотреть сообщение
this->m_vb.emplace_back(&obj, [](B*){});
конструктор смарт-поинтера выглядит так:
C++
1
template <class U, class D> shared_ptr (U* p, D del);
он может принимать указатель на ресурс,
и функтор, у которого имеется оператор()(B*)
когда смарту нужно будет удалить ресурс,
он сделает это руками функтора,
передав в качестве аргумента сырой указатель на свой ресурс.
соответственно, в функторе зашита логика по удалению ресурса.

в данном примере - ничего не делание.
и это ничего не делание позволяет запихивать туда указатели на объекты со стека,
и не бояться, что смарт их пригрохает.

Цитата Сообщение от zayats80888 Посмотреть сообщение
сылку дайте где почитать.
http://www.cplusplus.com/refer... hared_ptr/
Стратегия выделения/освобождения памяти
2
Комп_Оратор)
Эксперт по математике/физике
8719 / 4426 / 598
Регистрация: 04.12.2011
Сообщений: 13,262
Записей в блоге: 16
11.06.2019, 23:45 19
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Ну, во-первых, не надо давать "некту" их делитить.
Но это и значит, что если vector<shared_ptr<B*>> что-то и держит, то это не то, о чём стоит говорить. Потому что как только, появляется ещё один держатель, то всё что они держат, это то, что держит сам программист (вручную). И дай бог ему не нажить мозоли в данном разе.
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
12.06.2019, 19:30 20
Цитата Сообщение от zayats80888 Посмотреть сообщение
указатели на lvalue
Что этот набор слов означает?
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.06.2019, 19:30

Помощь в написании контрольных, курсовых и дипломных работ здесь.

C++: pointers, clases
Помогите, пожалуйста написать код для задачки Создать программу на языке С++, используя...

Указатели (Pointers)
Здравствуйте. Решил углубленно изучить указатели. Скачал несколько книг, лекций, тестов именно по...

Pointers and dynamic arrays
Изучаю тему указатели и динамичесские массивы в классах. Хотелось бы быть уверенным в следующих...

Const, pointers, reference
const int&amp; const ref1; const int &amp;ref1; int const &amp;ref1; Во всех случаях это константная...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.