. one of the most highly regarded and expertly designed C++ library projects in the world. — Herb Sutter and Andrei Alexandrescu, C++ Coding Standards
Содержание
- Purpose
- Example
- Synopsis
- template shared_ptr enable_shared_from_this ::shared_from_this();
- template shared_ptr enable_shared_from_this ::shared_from_this() const;
- template weak_ptr enable_shared_from_this ::weak_from_this() noexcept;
- template weak_ptr enable_shared_from_this ::weak_from_this() const noexcept;
- 6 Answers 6
- Решение
- Другие решения
Purpose
The header defines the class template enable_shared_from_this . It is used as a base class that allows a shared_ptr or a weak_ptr to the current object to be obtained from within a member function.
enable_shared_from_this defines two member functions called shared_from_this that return a shared_ptr and shared_ptr , depending on constness, to this . It also defines two member functions called weak_from_this that return a corresponding weak_ptr .
Example
Synopsis
template shared_ptr enable_shared_from_this ::shared_from_this();
template shared_ptr enable_shared_from_this ::shared_from_this() const;
Requires: enable_shared_from_this must be an accessible base class of T . *this must be a subobject of an instance t of type T .
Returns: If a shared_ptr instance p that owns t exists, a shared_ptr instance r that shares ownership with p .
Postconditions: r.get() == this .
Throws: bad_weak_ptr when no shared_ptr owns *this .
template weak_ptr enable_shared_from_this ::weak_from_this() noexcept;
template weak_ptr enable_shared_from_this ::weak_from_this() const noexcept;
Requires: enable_shared_from_this must be an accessible base class of T . *this must be a subobject of an instance t of type T .
Returns: If a shared_ptr instance p that owns t exists or has existed in the past, a weak_ptr instance r that shares ownership with p . Otherwise, an empty weak_ptr .
I ran across enable_shared_from_this while reading the Boost.Asio examples and after reading the documentation I am still lost for how this should correctly be used. Can someone please give me an example and/or and explanation of when using this class makes sense.
6 Answers 6
It enables you to get a valid shared_ptr instance to this , when all you have is this . Without it, you would have no way of getting a shared_ptr to this , unless you already had one as a member. This example from the boost documentation for enable_shared_from_this:
The method f() returns a valid shared_ptr , even though it had no member instance. Note that you cannot simply do this:
The shared pointer that this returned will have a different reference count from the «proper» one, and one of them will end up losing and holding a dangling reference when the object is deleted.
enable_shared_from_this has become part of C++ 11 standard. You can also get it from there as well as from boost.
from Dr Dobbs article on weak pointers, I think this example is easier to understand (source: http://drdobbs.com/cpp/184402026):
. code like this won’t work correctly:
Neither of the two shared_ptr objects knows about the other, so both will try to release the resource when they are destroyed. That usually leads to problems.
Similarly, if a member function needs a shared_ptr object that owns the object that it’s being called on, it can’t just create an object on the fly:
This code has the same problem as the earlier example, although in a more subtle form. When it is constructed, the shared_pt r object sp1 owns the newly allocated resource. The code inside the member function S::dangerous doesn’t know about that shared_ptr object, so the shared_ptr object that it returns is distinct from sp1 . Copying the new shared_ptr object to sp2 doesn’t help; when sp2 goes out of scope, it will release the resource, and when sp1 goes out of scope, it will release the resource again.
The way to avoid this problem is to use the class template enable_shared_from_this . The template takes one template type argument, which is the name of the class that defines the managed resource. That class must, in turn, be derived publicly from the template; like this:
When you do this, keep in mind that the object on which you call shared_from_this must be owned by a shared_ptr object. This won’t work:
Я хочу использовать boost сигналы2 с автоматическим управлением подключением в многопоточном приложении. Мой класс наследует от enable_shared_from_this и я хочу подключить метод-член из другого метода-члена. Соединение может часто перестраиваться, поэтому мой код должен быть настолько быстрым, насколько это возможно (несмотря на саму производительность сигналов сигнала2):
Я знаю, что мои цели разработки могут быть противоречивыми (автоматическое управление соединениями и безопасность потоков, но также быстрый код), но в любом случае:
Почему enable_shared_from_this отсутствие прямого доступа к встроенным weak_ptr ? Я не вижу противоположной причины. Нет ли варианта использования, аналогичного моему?
Есть ли более быстрое решение, чем приведенное выше?
Я знаю, что могу сделать что-то подобное, но я хочу избежать дополнительного наказания за хранение / инициализацию:
Решение
Причина, по которой у вас нет доступа к weak_ptr в том, что enable_shared_from_this не должен использовать один. Иметь weak_ptr это просто один возможный реализация enable_shared_from_this , Это не единственный.
поскольку enable_shared_from_this является частью той же стандартной библиотеки, что и shared_ptr можно использовать более эффективную реализацию, чем непосредственное хранение weak_ptr , И комитет не хочет предотвращать эту оптимизацию.
// хорошо, но медленно ?! два временных умных указателя
Это только один временный умный указатель. Копия elision / motion должна заботиться обо всем, кроме первого объекта.
Другие решения
Это может быть потому, что нет shared_ptr ссылаясь на Cat пример. weak_ptr требует, чтобы был хотя бы один активный shared_ptr ,
Попробуйте разместить shared_ptr в качестве переменной-члена и назначить ей сначала в connect метод:
Но в принципе не может быть никакого weak_ptr если нет shared_ptr ,
И если все shared_ptr исчезнуть в то время как weak_ptr все еще используется, то weak_ptr может указывать на несуществующий объект.
Примечание. Мой тест не следует использовать в производственном коде, поскольку он никогда не будет освобожден.
Источник: