C++ 当编译器试图优化/内联我的外观平庸但非平庸的dtor时,它会自食其果。或者,我做错了什么?

C++ 当编译器试图优化/内联我的外观平庸但非平庸的dtor时,它会自食其果。或者,我做错了什么?,c++,destructor,shared-ptr,pimpl-idiom,C++,Destructor,Shared Ptr,Pimpl Idiom,我有一个共享的pimpl*。它向前声明了实现对象,并有一个自定义实现的共享指针对象来实现pimpl习惯用法(同样,具有共享语义)。浓缩后,看起来是这样的: 福安 除了Foo和FooFactory之外,还有谁可能在呼叫~SharedPtr?这是从哪里来的?我如何修复它 注意:使~Foo虚拟化没有帮助,这对我来说更令人困惑 *impl是共享的这一事实在这里并不重要,我只是想阻止典型的“请定义一个复制/赋值方法”注释。pimpl指针是完全有意共享的 编辑:SharedPtr界面: 33

我有一个共享的pimpl*。它向前声明了实现对象,并有一个自定义实现的共享指针对象来实现pimpl习惯用法(同样,具有共享语义)。浓缩后,看起来是这样的:

福安 除了
Foo
FooFactory
之外,还有谁可能在呼叫
~SharedPtr
?这是从哪里来的?我如何修复它

注意:使
~Foo
虚拟化没有帮助,这对我来说更令人困惑


*impl是共享的这一事实在这里并不重要,我只是想阻止典型的“请定义一个复制/赋值方法”注释。pimpl指针是完全有意共享的


编辑:
SharedPtr
界面:

 33     template <typename T> struct Deallocator {
 34       private:
 35         bool doDelete; // not const to be def. assignable
 36       public:
 38         Deallocator(bool doDelete = true) : doDelete(doDelete) {}
 39         bool willDelete() const {
 40           return doDelete;
 41         }
 42         void operator()(T* t) const {
 43           if (doDelete)
 44             delete t;
 45         }
 46     };
 47
 48     template <typename T, typename Delete = Deallocator<T> > class SharedPtr : private SharedPtrBase {
 49       private:
 50         Delete del;
 51         T* ptr;
 52         void drop() {
 53           if (ptr && shouldDelete()) {
 54             del(ptr);
 55           }
 56           ptr = NULL;
 57           leave();
 58         }
 59       public:
 60         // SharedPtr(p,false) will not delete the pointer! Useful for Stackobjects!
 61         explicit SharedPtr(T* ptr = NULL, Delete del = Delete())
 62           : SharedPtrBase(), del(del), ptr(ptr) {
 63         }
 64         SharedPtr(SharedPtr const& from)
 65           : SharedPtrBase(from), del(from.del), ptr(from.ptr) {
 66         }
 67         ~SharedPtr() {
 68           drop();
 69         }
 70         SharedPtr& operator=(SharedPtr const& from) {
 71           if (&from != this) {
 72             drop();
 73             del = from.del;
 74             ptr = from.ptr;
 75             join(&from);
 76           }
 77           return *this;
 78         }
 79         SharedPtr& operator=(T* from) {
 80           return *this = SharedPtr(from,del);
 81         }
 ...
33模板结构解除定位器{
34私人:
35布尔·多德莱特;//不可定义为可赋值常量
36公众:
38 Deallocator(bool-doDelete=true):doDelete(doDelete){
39 bool willDelete()常量{
40返回多德莱特;
41         }
42 void运算符()(T*T)常量{
43如果(多德莱特)
44删除t;
45         }
46     };
47
48模板类SharedPtr:私有SharedPtrBase{
49私人:
50删除del;
51t*ptr;
52空投(){
53如果(ptr&&shouldDelete()){
54德尔(ptr);
55           }
56 ptr=NULL;
57离开();
58         }
59公众:
60//SharedPtr(p,false)不会删除指针!对Stackobjects有用!
61显式SharedPtr(T*ptr=NULL,Delete del=Delete())
62:SharedPtrBase(),del(del),ptr(ptr){
63         }
64 SharedPtr(SharedPtr const&from)
65:SharedPtrBase(from)、del(from.del)、ptr(from.ptr){
66         }
67~共享DPTR(){
68滴();
69         }
70 SharedPtr和运算符=(SharedPtr常量和发件人){
71如果(&从!=此){
72滴();
73 del=from.del;
74 ptr=from.ptr;
75加入(和来自);
76           }
77返回*本文件;
78         }
79 SharedPtr和运算符=(T*from){
80 return*this=SharedPtr(from,del);
81         }
...

您没有为
Foo
声明赋值运算符,因此如果您使用它,编译器将为您定义一个赋值运算符。编译器生成的赋值运算符将使用
SharedPtr
的copy赋值运算符,它通过许多中间函数在
Foo\u impl
上调用
delete


我看不到你的
Bar.cpp
,所以我不能说你可能在哪里复制
Foo
你没有为
Foo
声明赋值操作符,所以如果你使用它,编译器会为你定义一个。编译器生成的一个会使用
SharedPtr
的复制赋值操作符,它通过许多intermediate函数,在
Foo\u impl
上调用
delete


我看不到你的
Bar.cpp
所以我不能说你可能在哪里复制
Foo

什么是
SharedPtr
?当然不是
std::shared\u ptr
。@ildjarn:这是一个特定于项目的自定义共享指针类型。
Deallocator
也是一个自定义的
delete
包装器。你不认为它的实现n可能与您的问题有关..?请发布
SharedPtr
的定义。它可能要求模板参数在赋值运算符中是完整的类型。@ildjarn:我不明白为什么,它的工作原理基本上类似于
std::shared_ptr
,而不是有一个
显式
构造函数。但我会添加imple
Deallocator
——我想这可能很有用。什么是
SharedPtr
?当然不是
std::shared\u ptr
。@ildjarn:这是一种特定于项目的自定义共享指针类型。
Deallocator
也是一种自定义的
delete
包装器。而且您认为它的实现可能与您的问题无关n、 .?请发布
SharedPtr
的定义。它可能要求模板参数在赋值运算符中是完整的类型。@ildjarn:我不明白为什么,它的工作原理基本上类似于
std::shared\u ptr
,而不是有一个
显式
选择器。但我将添加
Deallocator
的实现>--我想这可能很有用。啊!谢谢。我现在定义了一个自定义销毁对象(因此它不会使用默认的
Deallocator
),但您的解释帮助我了解原始问题的来源。我没有看到。啊!谢谢。我现在定义了一个自定义销毁对象(因此它不会使用默认的
Deallocator
),但您的解释帮助我了解了原始问题的来源。我没有看到它。
#include "Foo.h"

Foo FooFactory::build() const {
  return Foo(SharedPtr<Foo_impl>(new Foo_impl(/*...*/)));
}
Foo::Foo(SharedPtr<Foo_impl> pimpl)
  : pimpl(pimpl) {
}
Foo::~Foo() {
}
SharedPtr.h: In member function ‘void Deallocator<T>::operator()(T*) const [with T = Foo_impl]’:
SharedPtr.h:54:   instantiated from ‘void SharedPtr<T, Delete>::drop() [with T = Foo_impl, Delete = Deallocator<Foo_impl>]’
SharedPtr.h:68:   instantiated from ‘SharedPtr<T, Delete>::~SharedPtr() [with T = Foo_impl, Delete = Deallocator<Foo_impl>]’
SharedPtr.h:44: warning: possible problem detected in invocation of delete operator:
SharedPtr.h:42: warning: ‘t’ has incomplete type
Foo.h:29: warning: forward declaration of ‘struct Foo_impl’
SharedPtr.h:44: note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined.
 33     template <typename T> struct Deallocator {
 34       private:
 35         bool doDelete; // not const to be def. assignable
 36       public:
 38         Deallocator(bool doDelete = true) : doDelete(doDelete) {}
 39         bool willDelete() const {
 40           return doDelete;
 41         }
 42         void operator()(T* t) const {
 43           if (doDelete)
 44             delete t;
 45         }
 46     };
 47
 48     template <typename T, typename Delete = Deallocator<T> > class SharedPtr : private SharedPtrBase {
 49       private:
 50         Delete del;
 51         T* ptr;
 52         void drop() {
 53           if (ptr && shouldDelete()) {
 54             del(ptr);
 55           }
 56           ptr = NULL;
 57           leave();
 58         }
 59       public:
 60         // SharedPtr(p,false) will not delete the pointer! Useful for Stackobjects!
 61         explicit SharedPtr(T* ptr = NULL, Delete del = Delete())
 62           : SharedPtrBase(), del(del), ptr(ptr) {
 63         }
 64         SharedPtr(SharedPtr const& from)
 65           : SharedPtrBase(from), del(from.del), ptr(from.ptr) {
 66         }
 67         ~SharedPtr() {
 68           drop();
 69         }
 70         SharedPtr& operator=(SharedPtr const& from) {
 71           if (&from != this) {
 72             drop();
 73             del = from.del;
 74             ptr = from.ptr;
 75             join(&from);
 76           }
 77           return *this;
 78         }
 79         SharedPtr& operator=(T* from) {
 80           return *this = SharedPtr(from,del);
 81         }
 ...