shared_ptr析构函数,复制和不完整类型

Rei*_*ica 5 c++ shared-ptr incomplete-type c++11

我有这样的头文件foo.h(省略了无关的东西):

#pragma once
#include <memory>

class Bar;


struct Foo
{
  std::shared_ptr<Bar> getBar();

  std::shared_ptr<const Bar> getBar() const
  {
    return const_cast<Foo*>(this)->getBar();
  }
};
Run Code Online (Sandbox Code Playgroud)

非const重载getBar()在.cpp文件中实现,该文件也可以看到完整定义Bar.

foo.h包含在另一个文件(没有看到定义Bar)时,VS 2010会给我一个这样的警告:

warning C4150: deletion of pointer to incomplete type 'Bar'; no destructor called
Run Code Online (Sandbox Code Playgroud)

在const重载getBar()(或实际上在从该重载实例化的标准库中的深处).

我的问题是这个警告是否可以安全地被忽略.

我看待它的方式,有两个std::shared_ptr<Bar>被调用的成员函数getBar() const:转换构造函数和析构函数.

// converting constructor
template <class Y>
std::shared_ptr<const Bar>::shared_ptr(std::shared_ptr<Y> &&r)
Run Code Online (Sandbox Code Playgroud)

这用于初始化返回值getBar() const的返回值getBar().这并未列出任何先决条件(C++ 1127.2.2.1§20-22),这些先决条件需要Y(Bar在我的情况下)完成.

// destructor
std::shared_ptr<const Bar>::~shared_ptr()
Run Code Online (Sandbox Code Playgroud)

27.2.2.2§1规定当被销毁的共享指针为空时,没有副作用.

我理解为什么我收到警告 - 析构函数代码也必须关注delete必须在存储指针上调用的情况,并且此代码确实会删除不完整的类型.但是我看到它的方式,在我的情况下永远无法实现,所以getBar() const是安全的.

我是正确的,还是我忽略了一个电话或其他可以getBar() const实际删除不完整类型的东西?

How*_*ant 7

我找不到警告的理由.我也不能用clang/libc ++复制警告.

在一般情况下,给定shared_ptr<Bar>,没有看到的建设shared_ptr<Bar>,需要一个Bar*和可选的删除器,也没有办法知道,如果~Bar()以往任何时候都调用.没有办法知道删除器存储在哪个shared_ptr<Bar>,并且给出了一些未知的删除器d,它存储在(例如)的shared_ptr<Bar>旁边,不需要调用.Bar*pd(p)~Bar()

例如,您Bar可能没有可访问的析构函数:

class Bar
{
    ~Bar();
};
Run Code Online (Sandbox Code Playgroud)

Foo::getBar()可以像这样实现:

std::shared_ptr<Bar>
Foo::getBar()
{
    // purposefully leak the Bar because you can't call ~Bar()
    return std::shared_ptr<Bar>(new Bar, [](Bar*){});
}
Run Code Online (Sandbox Code Playgroud)

如果没有看到foo.cpp,编译器就无法知道.

这个警告对我来说看起来像编译器错误,或者可能是执行中的错误std::shared_ptr.

你能忽略这个警告吗?我不知道.在我看来,你正在处理实现中的错误,因此bug很可能意味着警告是真实的.但是假设完全符合实现,我认为没有要求Bar在您显示的代码中成为完整类型.