首页 > 解决方案 > 为转发类型创建包含 unique_ptr 的类的 shared_ptr 失败

问题描述

这段代码

#include <memory>

class A {
public:
  class B;
  std::unique_ptr<B> b;
  A();
};

void foo() {
  std::make_shared<A>();
}

失败:

In file included from /usr/include/c++/7/memory:80:0,
                 from aaa.cpp:1:
/usr/include/c++/7/bits/unique_ptr.h: In instantiation of ‘void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = A::B]’:
/usr/include/c++/7/bits/unique_ptr.h:268:17:   required from ‘std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = A::B; _Dp = std::default_delete<A::B>]’
aaa.cpp:3:7:   required from ‘void __gnu_cxx::new_allocator<_Tp>::destroy(_Up*) [with _Up = A; _Tp = A]’
/usr/include/c++/7/bits/alloc_traits.h:487:4:   required from ‘static void std::allocator_traits<std::allocator<_Tp1> >::destroy(std::allocator_traits<std::allocator<_Tp1> >::allocator_type&, _Up*) [with _Up = A; _Tp = A; std::allocator_traits<std::allocator<_Tp1> >::allocator_type = std::allocator<A>]’
/usr/include/c++/7/bits/shared_ptr_base.h:535:35:   required from ‘void std::_Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp>::_M_dispose() [with _Tp = A; _Alloc = std::allocator<A>; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2]’
aaa.cpp:12:1:   required from here
/usr/include/c++/7/bits/unique_ptr.h:76:22: error: invalid application of ‘sizeof’ to incomplete type ‘A::B’
  static_assert(sizeof(_Tp)>0,

似乎编译器试图A::B为前向声明的类型定义默认删除。

有人可以解释为什么make_shared需要知道默认删除吗?以及如何克服呢?

标签: c++11

解决方案


同样的原因delete不适用于不完整的类型,shared_ptr也不是。

解决方案是提供自定义分配器功能:

#include <memory>

class A {
public:
  class B;
  std::unique_ptr<B> b;
  A();
};
std::shared_ptr<A> AMakeShared();

void foo() {
  AMakeShared();
}

函数的定义AMakeShared必须在定义A::B不完整的翻译单元中。假设另一个 file.cpp 包含:

class A::B {
}

std::shared_ptr<A> AMakeShared() {
    return std::make_shared<A>();
}

推荐阅读