深度探索C++对象模型 个人总结 第五章 构造、析构、拷贝、语意学
2021-03-08 17:27
标签:构造顺序 des 选择 data this virt 多重 全局变量 exp 可以定义和调用一个pure virtual function,不过只能被地调用。 pure virtual destructor必须定义它,因为每一个derived class destructor会被编译器扩张,以静态方式调用其“每一个virtual base class”以及“上一层base class”的destructor。假如缺乏了任意一个base class destructor的定义都会导致链接失败 一般的,不要把virtual destructor声明为pure 一般的,把所有成员函数都声明为virtual function,然后再靠编译器的优化操作把非必要的virtual invocation去除,并不是好的设计理念 不把virtual function声明为const,意味着函数不能够获得const reference或const pointer。声明为const却有可能遇到实际上derived instance必须修改某一个data member 其中的一个解决方法是:不再用const 对于POD(plain old data)类型, 定义一个对象时编译器不会调用其构造函数, 复制时也不会调用复制构造函数(或者是没定义), 而是像C语言那样的按位复制 在C中,global被视为“临时性的定义”,因为它没有显式初始化。可以在程序中发生多次但只保留一个实例,放入BSS。BSS(Block Started by Symbol)段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。 但在C++中不支持“临时性的定义”,global在C++中被视为完全定义(它会阻止第二个或更多定义)。 explicit initialization list的缺点: 1.只有当class member都是public,此法才奏效 2.只能指定常量,因为它们在编译期就可以被评估求值 3.由于编译器并没有自动施行之,所以初始化的失败可能性会高一些 virtual functions的导入促使每个class object拥有一个virtual table pointer,给我们提供了virtual接口的弹性时也额外增加了一个word的空间,但它是否有价值只有在实现完成之后才能评估是否避免 virtual functions的导入也引发编译器对于我们的class 产生膨胀作用: 1.所定义的constructor被附加了一些代码,以便将vptr初始化(base class constructor的调用之后,使用者供应代码之前) 2.合成一个copy constructor和一个copy assignment operator,且不再是trivial(但implicit destructor仍是trivial),不再bitwise 如果设计中有许多函数都需要以传值方式传回一个local class object,那么提供一个copy constructor就比较合理,能够触发NRV优化 constructor的调用真正伴随了什么? 1.所有virtual base class constructor必须被调用,从左到右,从最深到最浅: 如果class被列于member initialization list中,那么任何明确指定的参数都必须传递过去,否则如果class有一个default constructor,也应该调用它; class中的每一个virtual base class subobject的偏移量offset必须在执行期可被存取; 如果class object是最底层(most-derived)的class,其constructors可能被调用,某些用以支持这个行为的机制必须被放进来 2.以base class的声明次序调用上一层base class constructors: 如果base class被列于member initialization list中,那么任何明确指定的参数都必须传递过去,否则若它有default constructor或default memberwise copy constructor,那么就调用它; 如果base class是多重继承下的第二或后继的base class,那么this指针必须有所调整。 3.如果class object有virtual table pointer(s),它(们)必须被设定初值,指向适当的virtual table(s)。 4.如果有一个member没有出现在member initialization list中,但它有default constructor,调用之。 5.将member initialization list中的data members的初始化操作以members的声明次序放进constructor的函数本身。 只有当一个完整的class object被定义出来,“virtual base class constructors”才会被调用;如果object只是某个完整object的subobject,它就不会被调用 在一个class的constructor(和destructor)中,经由构造中的对象来调用一个virtual function,其实例应该是在此class中有作用的那个。这是因为constructor的调用顺序是由根源到末端、由内而外,当base classconstructor执行时,derived实例还没有被构造,此时还不是一个完整的对象。也因此在constructor(或destructor)中每一个调用操作以静态方式决议之 如果要在执行一个constructor时,必须限制一组virtual functions候选名单则vptr初始化操作应该在base class constructor调用操作之后,但是在程序员供应的代码或"member initialization list中所列members初始化操作“之前 constructor执行算法通常如下: 1.在derived class constructor中,”所有virtual base classes“及”上一层base class“的constructor会被调用 2.对象的vptr(s)被初始化,指向相关的virtual table(s) 3.如果有member initialization list的话此时将在constructor体内扩展开 4.最后执行程序员所提供的代码 当我们设计一个class,并以一个class object指定给另一个class object时的三种选择: 1.什么都不做,因此得以实施默认行为(要支持的只是一个简单的拷贝操作,那么默认行为不但足够而且有效率) 2.提供一个explicit copy assignment operator 3.显式地拒绝把一个class object指定给另一个class object(private或delete) 一个默认的copy assignment operator不会表现出bitwise copy语意: 1.当一个class内含的member object其class有一个copy assignment operator或它的base class有一个copy assignment operator 2.当一个class声明了任何virtual functions 3.当class继承自一个virtual base class C++ Standard上说copy assignment operator并不表示bitwise copy semantics是nontrivial。实际上,只有nontrivial才会被合成出来。 如果仅仅是为了把NRV优化开关打开而提供一个copy constructor,那么就没有必要一定要提供一个copy assignment operator。(这和三五法则相违背,可能是版本的不同导致的) 不要在任何virtual base class中声明数据 Plain OI‘ Data、或者是在其基础上加上数据封装以及inline函数的使用、或者是单一继承,多重继承表现出来的都是bitwise copy语意 当引入虚拟继承时不再允许class拥有bitwise copy语意,合成拷贝构造函数和合成的拷贝赋值运算符于是被产生出来,这导致了效率成本上的一个重大增加 如果class没有定义destructor,那么只有class内含member object(亦或是class自己的1base class)拥有destructor编译期才会自动合成出一个来,否则destructor被视为不需要,也就不需要被合成。(不管是拥有一个virtual function还是虚拟派生都是同理) destructor被扩展流程类似constructor被扩展的流程,但顺序刚好相反: 1.destructor的函数本体首先被执行; 2.如果class拥有member class objects,而后者拥有destructors,那么它们将以声明的相反顺序而调用; 3.如果object内带一个vptr,则现在被重新设定以指向适当base class之virtual table; 4.如果有任何直接的nonvirtual base classes拥有destructor,它们将以声明的相反顺序而调用; 5.如果有任何virtual base classes拥有destructor,而前面讨论的这个class是most-derived class,那么它们会以原先构造顺序的相反顺序被调用。 深度探索C++对象模型 个人总结 第五章 构造、析构、拷贝、语意学 标签:构造顺序 des 选择 data this virt 多重 全局变量 exp 原文地址:https://www.cnblogs.com/GodZhuan/p/14194643.html构造、析构、拷贝、语意学
纯虚函数的存在
虚拟规格的存在(Presence of a Virtual Specification)
虚拟规格中const的存在
重新考虑class的声明
5.1“无继承”情况下的对象构造
抽象数据类型
为继承做准备
5.2继承体系下的对象构造
虚拟继承
vptr初始化语意学
5.3对象复制语意学
5.4对象的效能
5.5析构语意学
文章标题:深度探索C++对象模型 个人总结 第五章 构造、析构、拷贝、语意学
文章链接:http://soscw.com/index.php/essay/61899.html