Inside the C++ Object Model 读书笔记(二)

本文围绕C++构造函数的语义展开,介绍了默认构造函数在成员类对象、基类、含虚函数类、含虚基类等情况下的非平凡构造条件,阐述了拷贝构造函数在四种实例下的情况,还涉及程序转换语义,包括参数初始化、返回值初始化、优化及成员初始化列表等内容。

The Semantics of Constructors

2.1 Default Constructor Construction

The C++ Annotated Reference Manual (ARM) [ELLIS90] tells us that “default constructors…are generated (by the compiler) where needed….”

Global objects are guaranteed to have their associated memory “zeroed out” at program start-up. Local objects allocated on the program stack and heap objects allocated on the free-store do not have their associated memory zeroed out; rather, the memory retains the arbitrary bit pattern of its previous use.

If there is no user-declared constructor for class X, a default constructor is implicitly declared…. A constructor is trivial if it is an implicitly declared default constructor….

A nontrivial default constructor is one that in the ARM’s terminology is needed by the implementation and, if necessary, is synthesized by the compiler( This synthesis, however, takes place only if the constructor actually needs to be invoked.). The next four sections look at the four conditions under which the default constructor is nontrivial.

1. Member Class Object with Default Constructor (user defined constructor)

An interesting question, then: Given the separate compilation model of C++, how does the compiler prevent synthesizing multiple default constructors, for example, one for file A.C and a second for file B.C? In practice, this is solved by having the synthesized default constructor, copy constructor, destructor, and/or assignment copy operator defined as inline

class Foo { public: Foo(), Foo( int ) ... }; 

class Bar { public: Foo foo; char *str; }; 

void foo_bar() { 
   Bar bar; // Bar::foo must be initialized here 
   if ( str ) { } ... 
} 

The synthesized default constructor here is nontrivial.

2. Base Class with Default Constructor

Similarly, if a class without any constructors is derived from a base class containing a default constructor, the default constructor for the derived class is considered nontrivial and so needs to be synthesized.

3. Class with a Virtual Function

A virtual function table is generated for that class. Within each class object, the vptr is synthesized to hold the address of the associated class vtbl. The compiler must initialize the vptr of each object.

4. Class with a Virtual Base Class

Virtual base class implementations vary widely across compilers.

class X { public: int i; }; 
class A : public virtual X   { public: int j; }; 
class B : public virtual X   { public: double d; }; 
class C : public A, public B { public: int k; }; 
// cannot resolve location of pa->X::i at compile-time 
void foo( const A* pa ) { pa->i = 1024; } 

main() { 
   foo( new A ); 
   foo( new C ); 
   // ... 
} 

the compiler cannot fix the physical offset of X::i accessed through pa within foo()

    // possible compiler transformation 
void foo( const A* pa ) { pa->__vbcX->i = 1024; } 

The initialization of __vbcX (or whatever implementation mechanism is used) is accomplished during the construction of the class object.

++The Standard refers to these as implicit, nontrivial default constructors.++

  • Common misunderstandings:
    • That a default constructor is synthesized for every class that does not define one

    • That the compiler-synthesized default constructor provides explicit default initializers for each data member declared within the class

2.2 Copy Constructor

Bitwise Copy Semantics—Not!

There are four instances:

  1. When the class contains a member object of a class for which a copy constructor exists (either explicitly declared by the class designer, as in the case of the previous String class, or synthesized by the compiler, as in the case of class Word)
  2. When the class is derived from a base class for which a copy constructor exists (again, either explicitly declared or synthesized)
  3. When the class declares one or more virtual functions
  4. When the class is derived from an inheritance chain in which one or more base classes are virtual
Resetting the Virtual Table Pointer

when a class declare one or more virtual fucntions:

  1. A virtual function table that contains the address of each active virtual function associated with that class (the vtbl) is generated.
  2. A pointer to the virtual function table is inserted within each class object (the vptr).

To reset vptr, compiler will synthesize a copy constructor in order to properly initialize the vptr.

Handling the Virtual Base Class Subobject

Each implementation’s support of virtual inheritance involves the need to make each virtual base class subobject’s location within the derived class object available at runtime. Maintaining the integrity of this location is the compiler’s responsibility. Bitwise copy semantics could result in a corruption of this location, so the compiler must intercede with its own synthesized copy constructor.

2.3 Program Transformation Semantics

Argument Initialization

The Standard states (Section 8.5) that passing a class object as an argument to a function (or as that function’s return value) is equivalent to the following form of initialization:

X xx = arg; 

an invocation of the form

X xx; 
// ... 
foo( xx ); 

would be transformed as follows:

// Pseudo C++ code 
// compiler generated temporary 
X __temp0; 

// compiler invocation of copy constructor 
__temp0.X::X ( xx ); 

// rewrite function call to take temporary 
foo( __temp0 );     //The declaration of foo() therefore must also be transformed void foo( X& x0 )

An alternative implementation is to copy construct the actual argument directly onto its place within the function’s activation record on the program stack. Prior to the return of the function, the local object’s destructor, if defined, is applied to it. The Borland C++ compiler, for example, implements this strategy.

Return Value Initialization
  1. Add an additional argument of type reference to the class object. This argument will hold the copy constructed “return value.”
  2. Insert an invocation of the copy constructor prior to the return statement to initialize the added argument with the value of the object being returned.
X bar() 
{ 
   X xx; 
   // process xx ... 
   return xx; 
}

transformed to

// function transformation to reflect 
// application of copy constructor 
// Pseudo C++ Code 
void 
bar( X& __result ) 
{ 
   X xx; 

   // compiler generated invocation 
   // of default constructor 
   xx.X::X(); 

   // ... process xx 
   // compiler generated invocation 
   // of copy constructor 
   __result.X::X( xx ); 

   return; 
} 
X xx = bar(); 


transform to :

X xx;   //Note: no constructor applied
bar( xx ); 

______________
bar().memfunc(); 

transformed to:
// compiler generated temporary 
X __temp0; 
( bar( __temp0 ), __temp0 ).memfunc(); 
Optimization

NRV: it is possible for the compiler itself to optimize the function by substituting the result argument for the named return value.

void 
bar( X &__result ) 
{ 
   // default constructor invocation 
   // Pseudo C++ Code 
   __result.X::X(); 

   // ... process in __result directly 

   return; 
} 

wheather or not to use NRV depends on compiler.

Member Initialization List

the compiler iterates over and possibly reorders the initialization list to reflect the declaration order of the members. It inserts the code within the body of the constructor prior to any explicit user code.

带开环升压转换器和逆变器的太阳能光伏系统 太阳能光伏系统驱动开环升压转换器和SPWM逆变器提供波形稳定、设计简单的交流电的模型 Simulink模型展示了一个完整的基于太阳能光伏的直流到交流电力转换系统,该系统由简单、透明、易于理解的模块构建而成。该系统从配置为提供真实直流输出电压的光伏阵列开始,然后由开环DC-DC升压转换器进行处理。升压转换器将光伏电压提高到适合为单相全桥逆变器供电的稳定直流链路电平。 逆变器使用正弦PWM(SPWM)开关来产生干净的交流输出波形,使该模型成为研究直流-交流转换基本操作的理想选择。该设计避免了闭环和MPPT的复杂性,使用户能够专注于光伏接口、升压转换和逆变器开关的核心概念。 此模型包含的主要功能: •太阳能光伏阵列在标准条件下产生~200V电压 •具有固定占空比操作的开环升压转换器 •直流链路电容器,用于平滑和稳定转换器输出 •单相全桥SPWM逆变器 •交流负载,用于观察实际输出行为 •显示光伏电压、升压输出、直流链路电压、逆变器交流波形和负载电流的组织良好的范围 •完全可编辑的结构,适合分析、实验和扩展 该模型旨在为太阳能直流-交流转换提供一个干净高效的仿真框架。布局简单明了,允许用户快速了解信号流,检查各个阶段,并根据需要修改参数。 系统架构有意保持模块化,因此可以轻松扩展,例如通过添加MPPT、动态负载行为、闭环升压控制或并网逆变器概念。该模型为进一步开发或整合到更大的可再生能源模拟中奠定了坚实的基础。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值