即使在 std::shared_ptr 拥有所有权之后,shared_from_this 也有空的 _M_weak_this

问题描述 投票:0回答:2

我使用 C++ 智能指针将一个类(我们称之为

A
)存储在
std::vector
中(因此向量签名为
std::vector<std::shared_ptr<A>>
)。

#include <iostream>
#include <memory>
#include <vector>

class A : std::enable_shared_from_this<A> {
public:
  void doWork();
  std::shared_ptr<A> getSharedRef();
};

void A::doWork() { std::cout << "Working..." << std::endl; }

std::shared_ptr<A> A::getSharedRef() { return shared_from_this(); }

class AManager {
  static std::vector<std::shared_ptr<A>> aList;

public:
  static void init(); // safety because statics
  static void doLotsOfWork();
  static std::shared_ptr<A> createA();
};

std::vector<std::shared_ptr<A>> AManager::aList;

void AManager::init() { aList = std::vector<std::shared_ptr<A>>{}; }

void AManager::doLotsOfWork() {
  for (auto a : aList) {
    a->doWork();
  }
}

std::shared_ptr<A> AManager::createA() {
  std::shared_ptr<A> a = std::make_shared<A>();

  aList.push_back(a);
  return a->getSharedRef(); // <----- EXCEPTION
}

int main() {
  AManager::init();
  AManager::createA();
  return 0;
}

由于某种原因,这会抛出一个

std::bad_weak_ptr
,经过检查,我注意到
a
,无论出于何种原因,其
_M_weak_this
等于
0x0
NULL
。由于我已经创建了一个引用该对象的有效
std::shared_ptr
,因此它不应该为空。

此外,我知道没有发生内存损坏,因为

A
(带有变量)在其地址上完全完好无损。

我做错了什么?

c++ c++11 vector stl shared-ptr
2个回答
14
投票

问题似乎是因为您是从

enable_shared_from_this

私有继承的

shared_from_this
要求“
enable_shared_from_this<T>
应是
T
的可访问基类。” (根据[util.smartptr.enab])

通过私有继承,基类不可访问,因此违反了先决条件。我认为这意味着未定义的行为。 Clang 和 GCC 都会抛出异常。

解决方案是公开继承。

class A :  public std::enable_shared_from_this<A> {
    //...
};

*在 C++17 中,措辞似乎已移至 [util.smartptr.shared.const],但要求基本相同。


0
投票

尽管 ~andyg 的答案是正确的,但将基类公开并不总是足够的。我遇到了这样的 nullptrweak_ptr 的困难情况,我必须找出困难的方法,即具有 public

std::enable_shared_from_this
基类的类不能位于匿名名称空间内。希望这些信息可以帮助将来的人!

© www.soinside.com 2019 - 2024. All rights reserved.