В следующем коде:
элемент данных интеллектуального указателя pImpl (класс Impl) и raw pointer pc (класс CAT) - это неполный тип данных, в Widget.h
нет определения этих двух классов,//widget.h
#ifndef W_H_
#define W_H_
#include <memory>
class Widget {
public:
Widget();
~Widget() { //
delete pc; // I know I should put ~Widget to .cpp
// I just want to show the difference in behavior
// between raw pointer and smart pointer(both has incomplete type)
// when widget object destructs
}
private:
struct Impl;
std::shared_ptr<Impl> pImpl; // use smart pointer
struct CAT;
CAT *pc; //raw pointer
};
#endif
//widget.cpp
#include "widget.h"
#include <string>
#include <vector>
#include <iostream>
using namespace std;
struct Widget::CAT
{
std::string name;
CAT(){cout<<"CAT"<<endl;}
~CAT(){cout<<"~CAT"<<endl;}
};
struct Widget::Impl {
std::string name;
Impl(){cout<<"Impl"<<endl;}
~Impl(){cout<<"~Impl"<<endl;}
};
Widget::Widget()
: pImpl(std::make_shared<Impl>()),
pc(new CAT)
{}
//main.cpp
#include "widget.h"
int main()
{
Widget w;
}
//выход
Impl
CAT
~ Impl
Для элемента данных с необработанным указателем его destuctor не называется, когда объект виджета разрушен.
В то время как элемент данных shared_ptr
, его деструктор был правильно вызван.
Насколько я понимаю, в Widget:: ~ Widget() он должен генерировать некоторые кода автоматически:
~Widget() {
delete pc; // wrote by me
// generated by compiler
delete pImpl->get();
}
Почему элемент данных shared_ptr и член исходных данных имеют другое поведение при удалении виджета?
Я тестирую код, используя g++ 4.8.2 в Linux
================================ EDIT ============== ================= Согласно ответам, причина в том, что:
код, сгенерированный компилятором, НЕ:
~Widget() {
delete pc; // wrote by me
// generated by compiler
delete pImpl->get();
}
это может быть что-то вроде:
~Widget() {
delete pc; // wrote by me
// generated by compiler
pimpl.deleter(); //deleter will be initailized while pimpl object is initialized
}