《吴咏炜To Be or Not to Be - On Object Lifetime.pdf》由会员分享,可在线阅读,更多相关《吴咏炜To Be or Not to Be - On Object Lifetime.pdf(57页珍藏版)》请在三个皮匠报告上搜索。
1、or对象生存期和相关工具吴咏炜To be,or not to be,that is the question.William Shakespeare,Hamlet,Act III,Scene iclass Obj public:Obj();Obj();void init();void cleanup();private:/数据成员;Obj*ptr=(Obj*)mmap();ptr-init();/开始使*ptr一点代码目 录CONTENTS1.存储期和生存期2.临时对象的生存期3.隐式生存期对象和可平凡复制对象4.工具 What is the answer to Life,the Univer
2、se,and Everything?What is the answer to Life,the Universe,and Everything?42.What is the answer to Life,the Universe,and Everything?42.Is 42 an object?*InspiredbyDouglasAdams,TheHitchhikersGuidetotheGalaxy 定义:为对象预留的内存空间所持续的时间 分类静态(static)线程(thread)自动(automatic)动态(dynamic)存储期 定义:对象从构造完成到析构开始的这段时间 生存期不
3、会超出存储期 在生存期之外访问对象是未定义行为 子对象的生存期生存期存储期和生存期 构造通常在进入main之前执行同一翻译单元内按定义的顺序不同翻译单元之间没有确定的顺序“静态初始化顺序陷阱”析构在main返回之后执行,顺序与析构相反全局变量和函数外的static 变量 第一次执行到变量定义时进行构造并发初始化也是线程安全的 程序退出时按与构造相反的顺序析构 Meyers 单例(Meyers singleton)可帮助解决静态初始化陷阱函数内的static 变量静态存储期对象/*A.h*/class A public:static A&instance();A(const A&)=delete
4、;A&operator=(const A&)=delete;private:A();A();/*A.cpp*/A&A:instance()static A a;return a;A:A()/*B.h*/class B public:static B&instance();B(const B&)=delete;B&operator=(const B&)=delete;private:B();B();/*B.cpp*/B&B:instance()static B b;return b;B:B()auto&a=A:instance();/使 aMeyers 单例解决静态初始化顺序问题 跟静态存储期对
5、象相似,但存储期和生存期跟线程(而非程序)绑定 每个线程都拥有变量的一个独立副本 函数内的 thread_local 变量会在当前线程首次执行到定义处进行构造(跟静态存储期相似)函数外的 thread_local 变量的构造时机依实现而定(GCC/Clang 的行为跟 MSVC 有区别)析构函数在线程退出时被调用,顺序跟构造顺序相反线程存储期对象 存储期和生存期紧密关联,都由编译器负责管理 代码执行到变量定义处(含参数声明处)进行构造,离开所在的作用域时析构 先构造的后析构 异常抛出时也会析构(stack unwinding)返回局部变量的引用或指针通常是一个错误自动存储期对象https:/g
6、odbolt.org/z/fjG5dMPr3(我的)定义:生存期由程序员手工管理的对象 生存期跟存储期绑定的情况 ptr=new Obj();delete ptr;生存期跟存储期脱钩的情况 std:byte buffersizeof(Obj);或auto buffer=mmap();ptr=new(buffer)Obj();ptr-Obj();“动态”对象 需确保对象的内存对齐要求得到满足 C+17 之前连 new Obj()都不能确保这一点 确保调用析构函数是在存储被释放或被重用之前 确保析构函数被调用 确保析构函数只被调用一次 确保在析构之后对象不会再被访问处理“动态”对象需要小心目 录C