Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
andrejap
13 / 13 / 1
Регистрация: 21.04.2013
Сообщений: 245
#1

Почему не дает shared_ptr от this? - C++

09.02.2015, 15:13. Просмотров 585. Ответов 5
Метки нет (Все метки)

Здравствуйте.
Вот проблемный код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
OwnProject::OwnProject(OwnManager * Manager, const QString & Filename)
    : manager(/*Manager->get_shared_ptr()*/ shared_ptr<OwnManager>(Manager)),
      filename(Filename)
{
    qDebug() << "[dbg]\t\tCalling c-tor for OwnProject (2nd)";
    nameOfProject =
            QFileInfo(filename).completeBaseName();
    file =
            make_shared<OwnProjectFile> (this, filename);
    rootNode =
            make_shared<OwnProjectNode> (this, file);
 
    Core::DocumentManager::addDocument(file.get(), false); //or true? or even - are we need this?
 
}
Если компилирую с закомментированным вариантом, а не тем, что далее "shared_ptr<OwnManager>(Manager)", то генерируется исключение:
terminate called after throwing an instance of 'std::bad_weak_ptr'
what() : bad_weak_ptr

OwnProject наследует std::enable_shared_from_this<OwnProject>, а get_shared_ptr это:
C++
1
2
3
4
5
6
std::shared_ptr<OwnProject> OwnProject::get_shared_ptr()
{
    qDebug() << "[dbg]\t\tGetting shared_ptr from this of OwnProject instance";
    return shared_from_this();
}
/*mem
Помогите, пожалуйста, ведь, это - "shared_ptr<OwnManager>(Manager)" - костыль?

P.S. Да, вызов в другом месте кода:
C++
1
return /*nullptr*/ new OwnProject(get_shared_ptr(), Filename);
другого конструктора:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
OwnProject::OwnProject(shared_ptr<Internal::OwnManager> Manager, const QString & Filename)
    : manager(Manager),
      filename(Filename)
{
    qDebug() << "[dbg]\t\tCalling c-tor for OwnProject (1st)";
    nameOfProject =
            QFileInfo(filename).completeBaseName();
    file =
            make_shared<OwnProjectFile> (this, filename);
    rootNode =
            make_shared<OwnProjectNode> (this, file);
 
    Core::DocumentManager::addDocument(file.get(), false); //or true? or even - are we need this?
    
}
приводит к тому самому.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.02.2015, 15:13     Почему не дает shared_ptr от this?
Посмотрите здесь:

C++ shared_ptr и vector
Наследование от shared_ptr C++
shared_ptr с потомками C++
shared_ptr валится C++
C++ Shared_ptr
C++ Шаблонный класс shared_ptr
Weak_ptr и shared_ptr C++
C++ Использование shared_ptr
Allocator и shared_ptr C++
C++ This для shared_ptr
Реализация shared_ptr C++
Shared_ptr runtime error C++

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

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
Модератор
Эксперт С++
7958 / 4720 / 319
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
09.02.2015, 15:56     Почему не дает shared_ptr от this? #2
andrejap, Есть shared_ptr-то который владеет Manager?
http://en.cppreference.com/w/cpp/mem...ared_from_this

Добавлено через 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
#include <memory>
#include <iostream>
 
class A : public std::enable_shared_from_this<A>
{
public:
   std::shared_ptr<A> get_shared() { return shared_from_this(); }
};
 
void function(A* ptr)
{
   auto safe_ptr = ptr->get_shared();
   std::cout << safe_ptr.use_count() << std::endl;
}
 
int main()
{
   auto a = std::make_shared<A>();
   auto c = a.get();
   function(a.get());
   a.reset();
   function(c);
}
andrejap
13 / 13 / 1
Регистрация: 21.04.2013
Сообщений: 245
09.02.2015, 16:56  [ТС]     Почему не дает shared_ptr от this? #3
ForEveR, то-есть, чтобы работала функция std::enable_shared_from_this<A>::shared_from_this() мало одного сырого указателя на тип A, нужен еще shared_ptr<A>, так ?

Цитата Сообщение от ForEveR Посмотреть сообщение
Есть shared_ptr-то который владеет Manager?
Ну во втором случает, я так понимаю - есть? С метода класса (не в конструкторе) можно вызывать функцию, вызывающую shared_from_this?
ForEveR
Модератор
Эксперт С++
7958 / 4720 / 319
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
09.02.2015, 17:59     Почему не дает shared_ptr от this? #4
andrejap, С метода класса можно вызывать функцию, вызывающую shared_from_this, если есть shared_ptr, который владеет данным объектов.

Добавлено через 6 минут
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 <memory>
#include <iostream>
 
void function(const std::function<void()>& user_callback)
{
   user_callback();
}
 
class A : public std::enable_shared_from_this<A>
{
public:
   static std::shared_ptr<A> create() { return std::make_shared<A>(); }
   A() {}
   void callback() {}
   void f()
   {
      function(std::bind(&A::callback, shared_from_this()));
   }
};
 
int main()
{
   auto a = A::create();
   a->f();
   A a1;
   a1.f();
}
В одном случае использование правильное, в другом нет.
hoggy
5974 / 2414 / 432
Регистрация: 15.11.2014
Сообщений: 5,355
Завершенные тесты: 1
09.02.2015, 18:28     Почему не дает shared_ptr от this? #5
Цитата Сообщение от andrejap Посмотреть сообщение
С метода класса (не в конструкторе) можно вызывать функцию, вызывающую shared_from_this?
если вкратце, то предполагается, что класс, который унаследован:
class A : public std::enable_shared_from_this<A>

Будет создаваться как ресурс смарт-поинтера (например помощи std::make_shared).

Функционал shared_from_this доступен только,
если этим объектом владеет какой нибудь смарт-поинтер.

-----------------------------------------------------------------------

Связи с этим, существует православное решение:
C++
1
2
3
4
5
6
7
8
9
10
11
class A : public std::enable_shared_from_this<A>
{
   A(){ ... } //<--- под запретом. 
public:
 
  static std::shared_ptr<A> make() //<--- создать объект можно только через фабрику
  {                       //которая проконтролирует, что объектом будет владеть смарт поинтер
       return std::make_shared<A>();
  }
   std::shared_ptr<A> get_shared() { return shared_from_this(); }
};
Таким образом, вызывающая сторона всегда взаимодействует со смарт-поинтером.
И тогда ресурс, которым он заряжен может безопасно возвращать свой shared_from_this()

---------------------------------------------------------

Вот такие вот вещи:

C++
1
2
auto c = a.get();
function(a.get());
Нужно делать очень аккуратно и осторожно.

Существует тезис:
"если класс выдал наружу указатель или ссылку на внутренние данные, то он больше не контролирует свой инвариант".

Если вы работаете со смарт-поинтером, то вы должны использовать интерфейс самого смарт-поинтера.

Сырые данные из него доставать следует только при крайней необходимости.
Потому что в этом случае, смарт-поинтер более вам ничего не гарантирует.
andrejap
13 / 13 / 1
Регистрация: 21.04.2013
Сообщений: 245
09.02.2015, 19:37  [ТС]     Почему не дает shared_ptr от this? #6
Спасибо за развернутые ответы, hoggy, ForEveR!!!
Yandex
Объявления
09.02.2015, 19:37     Почему не дает shared_ptr от this?
Ответ Создать тему
Опции темы

Текущее время: 22:38. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru