Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.86/7: Рейтинг темы: голосов - 7, средняя оценка - 4.86
278 / 250 / 209
Регистрация: 14.11.2016
Сообщений: 948
1

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

20.03.2020, 16:39. Показов 1391. Ответов 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)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
20.03.2020, 16:39
Ответы с готовыми решениями:

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

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

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

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

10
4333 / 2391 / 995
Регистрация: 07.02.2019
Сообщений: 6,271
20.03.2020, 16:44 2
Цитата Сообщение от anapshy Посмотреть сообщение
Каким образом передаем this, если по сути передаем _Wptr?
смотри перегрузку 11
1
6738 / 4537 / 1839
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
20.03.2020, 16:49 3
Цитата Сообщение от anapshy Посмотреть сообщение
Вопрос. Каким образом передаем this, если по сути передаем _Wptr?
shared_ptr и weak_ptr состоят из указателя на счётчик и указателя на объект. Поэтому enable_shared_from_this хранит weak_ptr в котором лежат this и указатель на счётчик (weak_ptr, а не shared_ptr, чтоб объект не держал сам себя)
1
278 / 250 / 209
Регистрация: 14.11.2016
Сообщений: 948
20.03.2020, 17:11  [ТС] 4
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
6738 / 4537 / 1839
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
20.03.2020, 17:20 5
Цитата Сообщение от 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
278 / 250 / 209
Регистрация: 14.11.2016
Сообщений: 948
20.03.2020, 17:22  [ТС] 6
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
6738 / 4537 / 1839
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
20.03.2020, 17:27 7
Лучший ответ Сообщение было отмечено 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
278 / 250 / 209
Регистрация: 14.11.2016
Сообщений: 948
20.03.2020, 17:32  [ТС] 8
Цитата Сообщение от 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
6738 / 4537 / 1839
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
20.03.2020, 17:33 9
Цитата Сообщение от anapshy Посмотреть сообщение
Но тогда данный this должен относиться к shared_ptr, раз он пишется в классе shared_ptr, а не к SharedObject. Что-то я совсем запутался.
_Px здесь равен this
1
278 / 250 / 209
Регистрация: 14.11.2016
Сообщений: 948
20.03.2020, 17:36  [ТС] 10
oleg-m1973, я как-то об этом и не подумал. Я подумал раз shared_from_this вызываем, то от этого и надо плясать(смотря исходники enable_shared_from_this > weak_ptr > _Ptr_base), а оказывается вся магия происходит в shared_ptr
0
6738 / 4537 / 1839
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
20.03.2020, 17:41 11
Цитата Сообщение от anapshy Посмотреть сообщение
oleg-m1973, я как-то об этом и не подумал. Я подумал раз shared_from_this вызываем, то от этого и надо плясать(смотря исходники enable_shared_from_this > weak_ptr> _Ptr_base), а оказывается вся магия происходит в shared_ptr
Ну да, как то так. Если ты не создашь shared_ptr для объекта, то и shared_from_this() у него будет пустым
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.03.2020, 17:41

Ошибка: 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::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;,...


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

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

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