c – 为什么不完整类型的智能指针数据成员和原始指针数据成员在
在以下代码中:
智能指针数据成员pImpl(类Impl)和原始指针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; } //输出
对于原始指针数据成员,当小部件对象被破坏时,它的destuctor不会被调用. 而shared_ptr数据成员,其析构函数已被正确调用. 据我了解,在Widget ::?Widget()中应该生成一些 ~Widget() { delete pc; // wrote by me // generated by compiler delete pImpl->get(); } 为什么在widget被破坏的时候,shared_ptr数据成员和原始数据成员有不同的行为? 我在Linux中使用g 4.8.2测试代码 ================================编辑================= ============== 编译器生成的代码不是: ~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 } 解决方法
因为您在头文件中转发声明“CAT”,所以您的数据类型不完整.使用这些信息,编译器将进入未定义的行为,析构函数可能不被调用.
什么标准说
在这里可以找到详细的说明:Why,really,deleting an incomplete type is undefined behaviour? struct CAT { std::string name; CAT(){std::cout<<"CAT"<<std::endl;} ~CAT(){std::cout<<"~CAT"<<std::endl;} }; class Widget { public: Widget(); ~Widget() { delete pc; // I know we should put this code to cpp // I am just want to show the difference behavior // between raw pointer and smart pointer // when widget object destruct } private: struct Impl; std::shared_ptr<Impl> pImpl; // use smart pointer CAT *pc; //raw pointer }; 并输出 Impl CAT ~CAT ~Impl 转发声明有助于加快编译时间,但是当需要有关数据类型的更多信息时可能会导致问题. 但为什么它可以用于智能指针? 基本上,在初始化或重置指针时,shared_ptr只需要声明.这意味着在声明的时刻不需要完整的类型.
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |