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

C++

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

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

09.02.2015, 15:13. Просмотров 629. Ответов 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?
    
}
приводит к тому самому.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.02.2015, 15:13
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Почему не дает shared_ptr от this? (C++):

Shared_ptr - C++
Всем хай. Есть некий класс и в нём такой метод: class Base { public: std::shared_ptr&lt;Base&gt; get_ptr() { ...

Allocator и shared_ptr - C++
Прокомментируйте пожалуйста. Есть ли смысл и вообще возможность оформлять зарезервированную память allocator-ом в shared_ptr? Или это...

shared_ptr и vector - C++
почему в vector нельзя засунуть shared_ptr ? ...

Использование shared_ptr - C++
std::shared_ptr&lt;int&gt; sp(new int); sp = 12; std::cout &lt;&lt; sp; Расшареному указателю нельзя присваивать стандартные...

shared_ptr валится - C++
#include &lt;iostream&gt; #include &lt;string&gt; using namespace std; #include &quot;boost/shared_ptr.hpp&quot; class One { public: ...

Реализация shared_ptr - C++
Добрый день. Реализовал shared_ptr(), но если больше 2 перемен он не правильно работает. Что я не правильно делаю и как правильно ...

5
ForEveR
В астрале
Эксперт С++
7978 / 4737 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
09.02.2015, 15:56 #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);
}
1
andrejap
13 / 13 / 1
Регистрация: 21.04.2013
Сообщений: 245
09.02.2015, 16:56  [ТС] #3
ForEveR, то-есть, чтобы работала функция std::enable_shared_from_this<A>::shared_from_this() мало одного сырого указателя на тип A, нужен еще shared_ptr<A>, так ?

Цитата Сообщение от ForEveR Посмотреть сообщение
Есть shared_ptr-то который владеет Manager?
Ну во втором случает, я так понимаю - есть? С метода класса (не в конструкторе) можно вызывать функцию, вызывающую shared_from_this?
0
ForEveR
В астрале
Эксперт С++
7978 / 4737 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
09.02.2015, 17:59 #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();
}
В одном случае использование правильное, в другом нет.
1
hoggy
6646 / 2832 / 485
Регистрация: 15.11.2014
Сообщений: 6,258
Завершенные тесты: 1
09.02.2015, 18:28 #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());
Нужно делать очень аккуратно и осторожно.

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

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

Сырые данные из него доставать следует только при крайней необходимости.
Потому что в этом случае, смарт-поинтер более вам ничего не гарантирует.
1
andrejap
13 / 13 / 1
Регистрация: 21.04.2013
Сообщений: 245
09.02.2015, 19:37  [ТС] #6
Спасибо за развернутые ответы, hoggy, ForEveR!!!
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.02.2015, 19:37
Привет! Вот еще темы с ответами:

Weak_ptr и shared_ptr - C++
Спасибо что зашли в эту тему и уделили мне время. Недавно увидел статью (не реклама) http://habrahabr.ru/post/191018/ Есть такой...

Наследование от shared_ptr - C++
Добрый день. Подскажите вот какую вещь. Сделал удобный для себя класс для ведения логов. В нем переопределил operator&lt;&lt; след....

shared_ptr с потомками - C++
Добрый вечер, сейчас столкнулся с задачей хранить большие объемы динамически-выделенной памяти. Обычный массив Base* list не подходит, т.к....

This для shared_ptr - C++
Как создать объект shared_ptr, в котором будет лежать this?


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

Или воспользуйтесь поиском по форуму:
6
Yandex
Объявления
09.02.2015, 19:37
Ответ Создать тему
Опции темы

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