Компилятор стреляет себе в ногу при попытке оптимизировать / встроить мой тривиально выглядящий, но нетривиальный dtor, что я делаю не так?

У меня есть этот общий прыщ *. Он объявляет объект реализации и имеет реализованный пользователем объект общего указателя для реализации идиомы pimpl (опять же, с семантикой совместного использования). Сгущенный, это выглядит так:

foo.h

#include "SharedPtr.h"

class Foo_impl;
class FooFactory;
class Foo {
  friend class FooFactory;
  private:
    SharedPtr<Foo_impl> pimpl;
    Foo(SharedPtr<Foo_impl>);
  public:
    ~Foo();
};
struct FooFactory {
  Foo build() const;
};

foo.cpp

#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() {
}

Теперь (я думаю) компилятор становится действительно умным при компиляции Bar.cpp (который использует Foo предметы и прочее SharedPtr объекты) и жалуется:

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.

Кто мог звонить ~SharedPtr<Foo_impl> Кроме как Foo а также FooFactory? Откуда это взялось и как я могу это исправить?

Примечание: изготовление ~Foo Виртуальный не помогает, что еще более загадочно для меня.


* Тот факт, что impl является общим, здесь не имеет значения, я просто хочу предотвратить типичные комментарии "пожалуйста, определите copy-ctor/assignment method". Это полностью намеренно, что указатель 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         }
 ...

1 ответ

Решение

Вы не объявляете оператор присваивания для Foo так что если вы используете его, компилятор определит его для вас. Сгенерированный компилятор будет использовать затем оператор копирования копии SharedPtr который через ряд промежуточных функций вызывает delete на Foo_impl,

Я не вижу твоего Bar.cpp так что я не могу сказать, где вы могли бы копировать Foo,

Другие вопросы по тегам