Слабый_птр, полученный из слабого_фромита (это) недействителен - PullRequest
2 голосов
/ 04 марта 2020

Вот минимальный пример для воспроизведения:

исходный код:

#include <memory>
#include <iostream>

class A : public std::enable_shared_from_this<A>
{
 public:
  A(std::weak_ptr<A> up) : up_(up)
  {
    std::cout << "A" << " has up_? " <<
        ((up_.lock()) ? "yes" : "no")
              << std::endl;
  }

  void grow()
  {
    if (dp_)
      dp_->grow();
    else
      dp_ = std::make_shared<A>(weak_from_this());
  }

 private:
  std::weak_ptr<A> up_;
  std::shared_ptr<A> dp_;
};

int main()
{
  auto wp = std::weak_ptr<A>();
  A a(wp);
  for (int i = 0; i < 3; ++i)
  {
    a.grow();
  }
  return 0;
}

оригинальный журнал:

clang++ minimal.cpp && ./a.out
A has up_? no
A has up_? no
A has up_? yes
A has up_? yes

желаемое поведение:

clang++ minimal.cpp && ./a.out
A has up_? no
A has up_? yes
A has up_? yes
A has up_? yes

На самом деле я хочу знать, почему вторая строка в исходном выводе говорит «нет»? Я думаю, что когда мы создаем объект типа A в первый раз (именно после того, как закончится его построение, и перед тем, как мы вызовем grow()), у нас будет действительный объект, на который мы можем передавать ссылки куда угодно, не так ли?

1 Ответ

6 голосов
/ 04 марта 2020

Из cppreference, около std::enable_shared_from_this::weak_from_this

Возвращает std::weak_ptr<T>, который отслеживает владение *this всеми существующими std::shared_ptr, которые относятся к *this.

Между тем

A a(wp);

Это не объект, который отслеживается любым shared_ptr. Это простой объект с автоматическим c сроком хранения. Если вы хотите, чтобы weak_from_this работал, shared_ptr должен отслеживать первый объект.

...