以下代码无法使用clang-700.1.81进行编译,而且是标准库:
#include <memory>
class something;
std::unique_ptr<something> external_function();
std::unique_ptr<something> local_function()
{
auto thing = external_function();
return thing;
}
clang的诊断:
......./include/c++/v1/memory:2626:46: note: in instantiation of member function 'std::__1::unique_ptr.....requested here
_LIBCPP_INLINE_VISIBILITY ~unique_ptr() {reset();}
^
test.cc:10:18: note: in instantiation of member function 'std::__1::unique_ptr<something, std::__1::default_delete<something> >::~unique_ptr' requested here
auto thing = external_function();
^
test.cc:4:7: note: forward declaration of 'something'
class something;
^
我猜它是在将它复制为返回值后试图销毁unique_ptr,但这是否真的有必要?无论如何它会被移动,它是否需要检查它是否可以复制,然后才意识到它更容易移动它?
我当然可以用裸指针轻松地做到这一点。 有没有其他方法允许uniqe_ptr只是“通过”翻译单元,如示例所示,不包含额外的标头来获取类的定义?
------ -------- EDIT 还尝试了GCC 5.3.0和gnu libstdc ++
不编译,也有类似的错误消息。
------ ---- EDIT
我认为它只是试图破坏原始thing
对象。
感谢Rudolf的删除想法(有点乱,但只有这个选项)
查看库代码,我在unique_ptr的代码中找到了它:
if (__tmp)
__ptr_.second()(__tmp);
其中second(_tmp)
破坏指向的对象。即使从未调用它,编译器也需要一个定义来编译它。这很愚蠢,但显然已经接受了它。
答案 0 :(得分:2)
std :: unique_ptr可以为不完整类型T构造,例如便于在Pimpl习语中用作句柄。如果使用默认删除器,则必须在调用删除器的代码中完成T,这发生在析构函数,移动赋值运算符和std :: unique_ptr的重置成员函数中。 (相反,std :: shared_ptr不能从原始指针构造为不完整类型,但可以在T不完整的情况下销毁。)
因此,使用自定义删除器,如果完整声明可用于删除器,则可以使用前向声明的类:
#include <memory>
class Foo;
class FooDeleter
{
public:
void operator()(Foo* pInstance);
};
std::unique_ptr<Foo, FooDeleter> pFoo;
class Foo
{
};
void FooDeleter::operator()(Foo* pInstance)
{
delete pInstance;
}