#c #c 11 #visual-c #c 17 #c 14
Вопрос:
У меня есть следующий фрагмент кода, который создает простой объект с именем, а внутри него создает другое имя объекта со shared_from_this()
ссылкой. Как я читаю отсюда https://en.cppreference.com/w/cpp/memory/enable_shared_from_this/shared_from_this
«Эффективно выполняет std::shared_ptr(weak_this), где weak_this является частным изменяемым членом std::weak_ptr для enable_shared_from_this».
Что я понимаю как shared_from_this (), только создает слабый указатель на общий объект. Но я не вижу, чтобы это имело место во время выполнения. Фактически создается циклическая ссылка.
В конце я ожидал, что имя obj должно быть уничтожено, но это не так, потому что счетчик ссылок равен 2.
Может ли кто-нибудь помочь мне понять , как я должен использовать enable_shared_from_this()
, чтобы эффективно очистить имя obj, как только оно выйдет из ссылки.
#include <iostream>
#include <memory>
#include <string>
#include <chrono>
#include <thread>
using namespace std;
struct Another;
struct Name : public std::enable_shared_from_this<Name> {
std::string t;
int m, n, p;
shared_ptr<Another> ann;
Name() {
std::cout << "constructorn";
}
void MakeSomething() {
ann = std::make_shared<Another>(shared_from_this());
}
~Name() {
std::cout << "destructorn";
}
};
struct Another {
shared_ptr<Name> nn;
Another(shared_ptr<Name> n) : nn(n) {
std::cout << "from another constructor " << nn.use_count() << "n";
}
~Another() {
std::cout << "from another destructorn";
}
};
int main()
{
{
auto n = std::make_shared<Name>();
std::cout << "Name ref count so far: " << n.use_count() << "n";
auto p = n.get();
//delete p;
std::cout << "Name ref count so far: " << n.use_count() << "n";
n->MakeSomething();
std::cout << "Name ref count so far: " << n.use_count() << "n";
{
shared_ptr<Name> m = n;
std::cout << "Name ref count so far: " << n.use_count() << "n";
}
std::cout << "Name ref count so far: " << n.use_count() << "n";
}
// problem: at this point Name obj, should go out of reference and destructor to be called, which is NOT happening
return 0;
}
А вот результат выполнения (компилятор использовал msvc)
constructor
Name ref count so far: 1
Name ref count so far: 1
from another constructor 3
Name ref count so far: 2
Name ref count so far: 3
Name ref count so far: 2
Комментарии:
1. У вас есть циклическая ссылка на shared_ptrs. Они никогда не выходят за рамки, потому что указывают друг на друга.
2. @Yksisarvinen да, я знаю об этом.
shared_from_this
создает циклическую ссылку, когда в документации говорится, что она создает слабую ссылку. Каким должен быть правильный способ использованияshared_from_this
3. Вероятно, вам нужно, чтобы один из них использовал std::weak_ptr
4. Это не имеет к этому никакого отношения
shared_from_this
. У вас есть двеshared_ptr
буквы «с», обе указывают друг на друга. Они не могут освободиться сами по себе, потому что никогда не бывает момента, когда либо заканчивается срок их жизни. Вам нужно будет отпустить (reset()
) один из них вручную, чтобы разорвать круг. Или один из них должен быть не ashared_ptr
, а aweak_ptr
или необработанный указатель, не являющийся владельцем.5. »
shared_from_this
создает круговую ссылку» — нет, это вы создали круговую ссылку. Если функцияshared_from_this
вызывается изолированно (не назначается чему-либо), она возвращает временный объект, который немедленно уничтожается. Дляann
создания круговой ссылки требуются ваши иnn
участники. Всеshared_from_this
, что было сделано, — это упрощение кода, создающего циклическую ссылку; это не является существенной частью этого кода.
Ответ №1:
Что я понимаю как shared_from_this (), только создает слабый указатель на общий объект. Но я не вижу, чтобы это имело место во время выполнения. Фактически создается циклическая ссылка.
shared_from_this()
это создание weak_ptr
, которое вы передаете shared_ptr
конструктору, как указано в (11) здесь. Этот конструктор создает a shared_ptr
для того же объекта, увеличивая количество ссылок.
Также имейте в виду, что weak_ptr
это вообще не влияет на количество ссылок, поэтому это не имеет никакого отношения к вашей путанице с количеством ссылок. Сосредоточьтесь на том, что shared_ptr
делают s.