Аватар для anapshy
531 / 272 / 220
Регистрация: 14.11.2016
Сообщений: 1,052

std::weak_ptr & std::enable_shared_for_this. Как передаем this?

20.03.2020, 16:39. Показов 2145. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
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
#include <iostream>
#include <memory>
 
class SharedObject : public std::enable_shared_from_this<SharedObject>
{
public:
    int x = 1;
    SharedObject() {}
    auto get() { return this->shared_from_this(); }
};
 
int main()
{
    {
 
        auto spt = std::shared_ptr<SharedObject>{ new SharedObject{} };
        auto spt2 = spt->get();
 
        // Change value
        spt->x *= 2;
 
        std::cout << "spt.use_count() = " << spt.use_count() << std::endl;
        std::cout << "spt2.use_count() = " << spt2.use_count() << std::endl;
        std::cout << "spt->x = " << spt->x << std::endl;
        std::cout << "spt2->x = " << spt2->x << std::endl;
    }
}
Создал smart pointer. Получил smart pointer на this. Изменил значение. Значение изменилось везде. Никаких претензий.
Заглянул под капот enable_shared_from_this:
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
// CLASS TEMPLATE enable_shared_from_this
template <class _Ty>
class enable_shared_from_this { // provide member functions that create shared_ptr to this
public:
    using _Esft_type = enable_shared_from_this;
 
    _NODISCARD shared_ptr<_Ty> shared_from_this() {
        return shared_ptr<_Ty>(_Wptr);
    }
 
    _NODISCARD shared_ptr<const _Ty> shared_from_this() const {
        return shared_ptr<const _Ty>(_Wptr);
    }
 
    _NODISCARD weak_ptr<_Ty> weak_from_this() noexcept {
        return _Wptr;
    }
 
    _NODISCARD weak_ptr<const _Ty> weak_from_this() const noexcept {
        return _Wptr;
    }
 
protected:
    constexpr enable_shared_from_this() noexcept : _Wptr() {}
 
    enable_shared_from_this(const enable_shared_from_this&) noexcept : _Wptr() {
        // construct (must value-initialize _Wptr)
    }
 
    enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept { // assign (must not change _Wptr)
        return *this;
    }
 
    ~enable_shared_from_this() = default;
 
private:
#if _HAS_IF_CONSTEXPR
    template <class _Yty>
    friend class shared_ptr;
#else // ^^^ _HAS_IF_CONSTEXPR // !_HAS_IF_CONSTEXPR vvv
    template <class _Other, class _Yty>
    friend void _Enable_shared_from_this1(const shared_ptr<_Other>& _This, _Yty* _Ptr, true_type) noexcept;
#endif // _HAS_IF_CONSTEXPR
 
    mutable weak_ptr<_Ty> _Wptr; /*    <-------------     */
};
Оказывается что тут у нас weak_ptr. Ф-я shared_from_this возвращает shared_ptr(_Wptr);.

Вопрос. Каким образом передаем this, если по сути передаем _Wptr?
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
20.03.2020, 16:39
Ответы с готовыми решениями:

std::filesystem && std::asio и пр
Пытался найти хоть какие-то сроки включения всего этого в стандарт (так же ожидается lexical_cast, any, string_algo и т.д.) и вообщем везде...

Не могу разобраться как обновить в std::map<std::string, вектор_структур>
Не могу разобраться как обновить вектор структур после его добавления в map без удаления и перезаписи struct pStruct { int...

std::string, std::fstream, ошибка кучи
где то начало вылетать при операции += с локальной переменной std::string. Заменил на свой qString. Замечательно, то же самое... ошибка при...

10
 Аватар для zayats80888
6345 / 3516 / 1428
Регистрация: 07.02.2019
Сообщений: 8,982
20.03.2020, 16:44
Цитата Сообщение от anapshy Посмотреть сообщение
Каким образом передаем this, если по сути передаем _Wptr?
смотри перегрузку 11
1
6771 / 4565 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
20.03.2020, 16:49
Цитата Сообщение от anapshy Посмотреть сообщение
Вопрос. Каким образом передаем this, если по сути передаем _Wptr?
shared_ptr и weak_ptr состоят из указателя на счётчик и указателя на объект. Поэтому enable_shared_from_this хранит weak_ptr в котором лежат this и указатель на счётчик (weak_ptr, а не shared_ptr, чтоб объект не держал сам себя)
1
 Аватар для anapshy
531 / 272 / 220
Регистрация: 14.11.2016
Сообщений: 1,052
20.03.2020, 17:11  [ТС]
zayats80888, oleg-m1973, где же этот самый this ? Откуда объект _Wptr может знать об указателе на текущий объект SharedObject (this), если проинициализирован конструктором по умолчанию, который в свою очередь по сути не делает ничего?
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
template <class _Ty>
class _Ptr_base { // base class for shared_ptr and weak_ptr
public:
    using element_type = remove_extent_t<_Ty>;
 
    _NODISCARD long use_count() const noexcept {
        return _Rep ? _Rep->_Use_count() : 0;
    }
 
    template <class _Ty2>
    _NODISCARD bool owner_before(const _Ptr_base<_Ty2>& _Right) const noexcept { // compare addresses of manager objects
        return _Rep < _Right._Rep;
    }
 
    _Ptr_base(const _Ptr_base&) = delete;
    _Ptr_base& operator=(const _Ptr_base&) = delete;
 
protected:
    _NODISCARD element_type* get() const noexcept {
        return _Ptr;
    }
 
    constexpr _Ptr_base() noexcept = default;
 
    ~_Ptr_base() = default;
 
    template <class _Ty2>
    void _Move_construct_from(_Ptr_base<_Ty2>&& _Right) noexcept {
        // implement shared_ptr's (converting) move ctor and weak_ptr's move ctor
        _Ptr = _Right._Ptr;
        _Rep = _Right._Rep;
 
        _Right._Ptr = nullptr;
        _Right._Rep = nullptr;
    }
 
    template <class _Ty2>
    void _Copy_construct_from(const shared_ptr<_Ty2>& _Other) noexcept {
        // implement shared_ptr's (converting) copy ctor
        if (_Other._Rep) {
            _Other._Rep->_Incref();
        }
 
        _Ptr = _Other._Ptr;
        _Rep = _Other._Rep;
    }
 
    template <class _Ty2>
    void _Alias_construct_from(const shared_ptr<_Ty2>& _Other, element_type* _Px) noexcept {
        // implement shared_ptr's aliasing ctor
        if (_Other._Rep) {
            _Other._Rep->_Incref();
        }
 
        _Ptr = _Px;
        _Rep = _Other._Rep;
    }
 
    template <class _Ty2>
    void _Alias_move_construct_from(shared_ptr<_Ty2>&& _Other, element_type* _Px) noexcept {
        // implement shared_ptr's aliasing move ctor
        _Ptr = _Px;
        _Rep = _Other._Rep;
 
        _Other._Ptr = nullptr;
        _Other._Rep = nullptr;
    }
 
    template <class _Ty0>
    friend class weak_ptr; // specifically, weak_ptr::lock()
 
    template <class _Ty2>
    bool _Construct_from_weak(const weak_ptr<_Ty2>& _Other) noexcept {
        // implement shared_ptr's ctor from weak_ptr, and weak_ptr::lock()
        if (_Other._Rep && _Other._Rep->_Incref_nz()) {
            _Ptr = _Other._Ptr;
            _Rep = _Other._Rep;
            return true;
        }
 
        return false;
    }
 
    void _Decref() noexcept { // decrement reference count
        if (_Rep) {
            _Rep->_Decref();
        }
    }
 
    void _Swap(_Ptr_base& _Right) noexcept { // swap pointers
        _STD swap(_Ptr, _Right._Ptr);
        _STD swap(_Rep, _Right._Rep);
    }
 
    template <class _Ty2>
    void _Weakly_construct_from(const _Ptr_base<_Ty2>& _Other) noexcept { // implement weak_ptr's ctors
        if (_Other._Rep) {
            _Ptr = _Other._Ptr;
            _Rep = _Other._Rep;
            _Rep->_Incwref();
        } else {
            _STL_INTERNAL_CHECK(!_Ptr && !_Rep);
        }
    }
 
    void _Decwref() noexcept { // decrement weak reference count
        if (_Rep) {
            _Rep->_Decwref();
        }
    }
 
private:
    element_type* _Ptr{nullptr};
    _Ref_count_base* _Rep{nullptr};
 
    template <class _Ty0>
    friend class _Ptr_base;
 
    friend shared_ptr<_Ty>;
 
    friend _Exception_ptr_access;
 
#if _HAS_STATIC_RTTI
    template <class _Dx, class _Ty0>
    friend _Dx* get_deleter(const shared_ptr<_Ty0>& _Sx) noexcept;
#endif // _HAS_STATIC_RTTI
};
 
 
// CLASS TEMPLATE weak_ptr
template <class _Ty>
class weak_ptr : public _Ptr_base<_Ty> { // class for pointer to reference counted resource
public:
    constexpr weak_ptr() noexcept {} // construct empty weak_ptr object
 
    weak_ptr(const weak_ptr& _Other) noexcept { // construct weak_ptr object for resource pointed to by _Other
        this->_Weakly_construct_from(_Other);
    }
 
    template <class _Ty2, enable_if_t<_SP_pointer_compatible<_Ty2, _Ty>::value, int> = 0>
    weak_ptr(const shared_ptr<_Ty2>& _Other) noexcept { // construct weak_ptr object for resource owned by _Other
        this->_Weakly_construct_from(_Other);
    }
 
    template <class _Ty2, enable_if_t<_SP_pointer_compatible<_Ty2, _Ty>::value, int> = 0>
    weak_ptr(const weak_ptr<_Ty2>& _Other) noexcept { // construct weak_ptr object for resource pointed to by _Other
        this->_Weakly_construct_from(_Other.lock());
    }
 
    weak_ptr(weak_ptr&& _Other) noexcept { // move construct from _Other
        this->_Move_construct_from(_STD move(_Other));
    }
 
    template <class _Ty2, enable_if_t<_SP_pointer_compatible<_Ty2, _Ty>::value, int> = 0>
    weak_ptr(weak_ptr<_Ty2>&& _Other) noexcept { // move construct from _Other
        this->_Weakly_construct_from(_Other.lock());
        _Other.reset();
    }
 
    ~weak_ptr() noexcept {
        this->_Decwref();
    }
 
    weak_ptr& operator=(const weak_ptr& _Right) noexcept {
        weak_ptr(_Right).swap(*this);
        return *this;
    }
 
    template <class _Ty2>
    weak_ptr& operator=(const weak_ptr<_Ty2>& _Right) noexcept {
        weak_ptr(_Right).swap(*this);
        return *this;
    }
 
    weak_ptr& operator=(weak_ptr&& _Right) noexcept {
        weak_ptr(_STD move(_Right)).swap(*this);
        return *this;
    }
 
    template <class _Ty2>
    weak_ptr& operator=(weak_ptr<_Ty2>&& _Right) noexcept {
        weak_ptr(_STD move(_Right)).swap(*this);
        return *this;
    }
 
    template <class _Ty2>
    weak_ptr& operator=(const shared_ptr<_Ty2>& _Right) noexcept {
        weak_ptr(_Right).swap(*this);
        return *this;
    }
 
    void reset() noexcept { // release resource, convert to null weak_ptr object
        weak_ptr().swap(*this);
    }
 
    void swap(weak_ptr& _Other) noexcept {
        this->_Swap(_Other);
    }
 
    _NODISCARD bool expired() const noexcept {
        return this->use_count() == 0;
    }
 
    _NODISCARD shared_ptr<_Ty> lock() const noexcept { // convert to shared_ptr
        shared_ptr<_Ty> _Ret;
        (void) _Ret._Construct_from_weak(*this);
        return _Ret;
    }
};
0
6771 / 4565 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
20.03.2020, 17:20
Цитата Сообщение от anapshy Посмотреть сообщение
zayats80888, oleg-m1973, где же этот самый this ? Откуда объект _Wptr может знать об указателе на текущий объект SharedObject (this), если проинициализирован конструктором по умолчанию, который в свою очередь по сути не делает ничего?
std::shared_ptr проставляет туда this при создании

Добавлено через 2 минуты
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   template <class _Ux>
    void _Set_ptr_rep_and_enable_shared(_Ux* const _Px, _Ref_count_base* const _Rx) noexcept { // take ownership of _Px
        this->_Ptr = _Px;
        this->_Rep = _Rx;
#if _HAS_IF_CONSTEXPR
        if constexpr (conjunction_v<negation<is_array<_Ty>>, negation<is_volatile<_Ux>>, _Can_enable_shared<_Ux>>) {
            if (_Px && _Px->_Wptr.expired()) {
                _Px->_Wptr = shared_ptr<remove_cv_t<_Ux>>(*this, const_cast<remove_cv_t<_Ux>*>(_Px));
            }
        }
#else // ^^^ _HAS_IF_CONSTEXPR // !_HAS_IF_CONSTEXPR vvv
        _Enable_shared_from_this1(*this, _Px,
            bool_constant<
                conjunction_v<negation<is_array<_Ty>>, negation<is_volatile<_Ux>>, _Can_enable_shared<_Ux>>>{});
#endif // _HAS_IF_CONSTEXPR
    }
C++
1
2
3
4
5
        if constexpr (conjunction_v<negation<is_array<_Ty>>, negation<is_volatile<_Ux>>, _Can_enable_shared<_Ux>>) {
            if (_Px && _Px->_Wptr.expired()) {
                _Px->_Wptr = shared_ptr<remove_cv_t<_Ux>>(*this, const_cast<remove_cv_t<_Ux>*>(_Px));
            }
        }
1
 Аватар для anapshy
531 / 272 / 220
Регистрация: 14.11.2016
Сообщений: 1,052
20.03.2020, 17:22  [ТС]
oleg-m1973, примерно так?!
C++
1
2
3
4
5
_NODISCARD shared_ptr<_Ty> lock() const noexcept { // convert to shared_ptr
        shared_ptr<_Ty> _Ret;
        (void) _Ret._Construct_from_weak(*this);
        return _Ret;
    }
Добавлено через 2 минуты
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
std::shared_ptr проставляет туда this при создании
а разве это тот this о котором мы говорим?!
0
6771 / 4565 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
20.03.2020, 17:27
Лучший ответ Сообщение было отмечено anapshy как решение

Решение

Цитата Сообщение от anapshy Посмотреть сообщение
oleg-m1973, примерно так?!
Причём здесь lock()? В конструкторе shared_ptr(T *)

Добавлено через 4 минуты
C++
1
2
3
4
5
6
7
struct CTest: std::enable_shared_from_this<CTest>
{
};
 
 
auto *p = new CTest; //shared_from_this() == nullptr
std::shared_ptr<CTest> sp(p); //HERE!!!!!!
1
 Аватар для anapshy
531 / 272 / 220
Регистрация: 14.11.2016
Сообщений: 1,052
20.03.2020, 17:32  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
В конструкторе shared_ptr(T *)
C++
1
_Px->_Wptr = shared_ptr<remove_cv_t<_Ux>>(*this, const_cast<remove_cv_t<_Ux>*>(_Px));
Но тогда данный this должен относиться к shared_ptr, раз он пишется в классе shared_ptr, а не к SharedObject. Что-то я совсем запутался.

Добавлено через 47 секунд
oleg-m1973, ааааааааа, теперь понял. Всё. Спасибо))
0
6771 / 4565 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
20.03.2020, 17:33
Цитата Сообщение от anapshy Посмотреть сообщение
Но тогда данный this должен относиться к shared_ptr, раз он пишется в классе shared_ptr, а не к SharedObject. Что-то я совсем запутался.
_Px здесь равен this
1
 Аватар для anapshy
531 / 272 / 220
Регистрация: 14.11.2016
Сообщений: 1,052
20.03.2020, 17:36  [ТС]
oleg-m1973, я как-то об этом и не подумал. Я подумал раз shared_from_this вызываем, то от этого и надо плясать(смотря исходники enable_shared_from_this > weak_ptr > _Ptr_base), а оказывается вся магия происходит в shared_ptr
0
6771 / 4565 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
20.03.2020, 17:41
Цитата Сообщение от anapshy Посмотреть сообщение
oleg-m1973, я как-то об этом и не подумал. Я подумал раз shared_from_this вызываем, то от этого и надо плясать(смотря исходники enable_shared_from_this > weak_ptr> _Ptr_base), а оказывается вся магия происходит в shared_ptr
Ну да, как то так. Если ты не создашь shared_ptr для объекта, то и shared_from_this() у него будет пустым
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
20.03.2020, 17:41
Помогаю со студенческими работами здесь

Как проинициализировать std::stack<const int> obj ( std::stack<int>{} );
добрый день. вопрос в коде: http://rextester.com/VCVVML6656 #include &lt;iostream&gt; #include &lt;stack&gt; //-std=c++14...

Ошибка: E2034 Cannot convert 'int' to 'std::vector<std::vector<TRabbitCell,std::allocator<TRabbitCell>>...
Есть двухмерный вектор: std::vector&lt;std::vector&lt;TRabbitCell&gt; &gt; *cells(5, 10); Пытаюсь заполнить его объектами класса...

Перевод строк std::string, std::wstring в Unicode (String)
Собственно столкнулся с проблемой, как корректно перевести к примеру текст из Edit1-&gt;Text в std::string или std::wstring и...

Выделение памяти для буффера, под std::istream& operator>>(std::istream &, String &)
Добрый день. Как осуществляется выделения памяти под перегруженный оператор ввода данных в пользовательский тип? Ведь мы заранее не можем...

(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&
astxx::manager::connection::connection(std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; const&amp;, unsigned short); ...


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

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

Новые блоги и статьи
Angular: Вопросы и ответы на собеседовании
Reangularity 15.06.2025
Готовишься к техническому интервью по Angular? Я собрал самые распространенные вопросы, с которыми сталкиваются разработчики на собеседованиях в этом году. От базовых концепций до продвинутых. . .
Архитектура Onion в ASP.NET Core MVC
stackOverflow 15.06.2025
Что такое эта "луковая" архитектура? Термин предложил Джеффри Палермо (Jeffrey Palermo) в 2008 году, и с тех пор подход только набирал обороты. Суть проста - представьте себе лук с его. . .
Unity 4D
GameUnited 13.06.2025
Четырехмерное пространство. . . Звучит как что-то из научной фантастики, правда? Однако для меня, как разработчика со стажем в игровой индустрии, четвертое измерение давно перестало быть абстракцией из. . .
SSE (Server-Sent Events) в ASP.NET Core и .NET 10
UnmanagedCoder 13.06.2025
Кажется, Microsoft снова подкинула нам интересную фичу в новой версии фреймворка. Работая с превью . NET 10, я наткнулся на нативную поддержку Server-Sent Events (SSE) в ASP. NET Core Minimal APIs. Эта. . .
С днём независимости России!
Hrethgir 13.06.2025
Решил побеседовать, с утра праздничного дня, с LM о завоеваниях. То что она написала о народе, представителем которого я являюсь сам сначала возмутило меня, но дальше только смешило. Это чисто. . .
Лето вокруг.
kumehtar 13.06.2025
Лето вокруг. Наполненное бурями и ураганами событий. На фоне магии Жизни, священной и вечной, неумелой рукой человека рисуется панорама душевного непокоя. Странные серые краски проникают и. . .
Популярные LM модели ориентированы на увеличение затрат ресурсов пользователями сгенерированного кода (грязь -заслуги чистоплюев).
Hrethgir 12.06.2025
Вообще обратил внимание, что они генерируют код (впрочем так-же ориентированы разработчики чипов даже), чтобы пользователь их использующий уходил в тот или иной убыток. Это достаточно опытные модели,. . .
Топ10 библиотек C для квантовых вычислений
bytestream 12.06.2025
Квантовые вычисления - это та область, где теория встречается с практикой на границе наших знаний о физике. Пока большая часть шума вокруг квантовых компьютеров крутится вокруг языков высокого уровня. . .
Dispose и Finalize в C#
stackOverflow 12.06.2025
Работая с C# больше десяти лет, я снова и снова наблюдаю одну и ту же историю: разработчики наивно полагаются на сборщик мусора, как на волшебную палочку, которая решит все проблемы с памятью. Да,. . .
Повышаем производительность игры на Unity 6 с GPU Resident Drawer
GameUnited 11.06.2025
Недавно копался в новых фичах Unity 6 и наткнулся на GPU Resident Drawer - штуку, которая заставила меня присвистнуть от удивления. По сути, это внутренний механизм рендеринга, который автоматически. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru