我在标题中有一些代码,看起来像这样:

#include <memory>

class Thing;

class MyClass
{
    std::unique_ptr< Thing > my_thing;
};

如果我在一个不包括Thing类型定义的cpp中包含这个头,那么这不会在VS2010-SP1下编译:

1>C:\程序文件(x86)\微软 Visual Studio 10.0\VC\include\memory(2067):错误C2027:使用未定义的类型'Thing'

将std::unique_ptr替换为std::shared_ptr并进行编译。

所以,我猜是当前的VS2010 std::unique_ptr的实现需要完整的定义,它完全依赖于实现。

真的是这样吗?它的标准要求中是否有一些东西使得std::unique_ptr的实现不可能只使用前向声明?这感觉很奇怪,因为它应该只持有一个指向Thing的指针,不是吗?


当前回答

这与实现无关。它起作用的原因是shared_ptr决定在运行时调用的正确析构函数——它不是类型签名的一部分。但是,unique_ptr的析构函数是其类型的一部分,必须在编译时知道它。

其他回答

对我来说,

QList<QSharedPointer<ControllerBase>> controllers;

只包括标题…

#include <QSharedPointer>

简单的答案是使用shared_ptr代替。

编译器需要Thing的定义来为MyClass生成默认析构函数。如果显式声明析构函数并将其(空)实现移动到CPP文件,则代码应该被编译。

我正在寻找一种方法来使用PIMPL习语与std::unique_ptr。这个指南是一个很好的资源。

简而言之,以下是你可以做的事情:

my_class.h

#include <memory>

class Thing;

class MyClass
{
    ~MyClass(); // <--- Added
    std::unique_ptr< Thing > my_thing;
};

my_class.cpp

MyClass::~MyClass() = default; // Or a custom implementation

这与实现无关。它起作用的原因是shared_ptr决定在运行时调用的正确析构函数——它不是类型签名的一部分。但是,unique_ptr的析构函数是其类型的一部分,必须在编译时知道它。