编译期初始化与运行期初始化

编译期初始化:在源代码被编译过程中,编译期安插一些代码逻辑,完成确定的内存分配(并非实际分配内存,而是确定其大小占用,由编译期安插代码),变量的初始化。

 

如:全局变量为内置类型,并且大小确定

int a=2; 
static int b=3;   //static的不同只是其只在本文件中可见
static int c=a+b;

在编译期初始化,那么在实际运行期都是确定的结构和逻辑,将带来更高的性能,因为编译器完成了一定的工作。

 

加载时初始化:在main()函数执行前,完成包括全局变量,静态变量的初始化:

例如全局的类对象:

class A
{
public:
    virtual void fun()
    {
        cout<<"funciton A:fun() call"<<endl;
    }


};
A a;//将在main执行前,加载时初始化

int main()
{

......

全局类对象在main函数执行前,由加载程序完成其初始化,其无法在编译期初始化,由于那时候还无法调用类的构造函数。

同时,在加载期,是线程安全的。例如,饿汉方式的单例类:

借助main执行前的加载期完成初始化,由于还在加载所以确保线程安全。

class A
{
private:
    A(){}

    static A* instance;
public:
    static A* getInstance()
    {
        return instance;
    }


};
A* A::instance=new A();

int main()
{

   
}

 

运行期初始化:

指代实际程序运行期间对象(变量)的创建,包含那些动态创建的对象。由于编译和加载时无法确定大小,因此它们只能延迟到运行期才能完成初始化,将带来程序的性能开销。并且由于运行期间可能是多线程环境,对于共享变量,还可能带来线程安全问题。

int main()
{
   int* p=new int[N];
   A* arr=new A(0);

}

另外针对静态变量,若其是普通的具有本文可见性的普通静态变量

其可能在编译期(内置类型)初始化或者在加载期(类的静态成员)初始化。

但针对函数内部的局部static变量,其在第一次被调用时初始化,并且只初始化一次

 

语言的语法是针对源代码是否违反规定,其发生在编译期,一般认为在编译期出现的错误是及时有效的,而不至于延迟到运行期再发生错误,那样更为不可控。

一个常见的例子是,类的访问权限只会在编译期进行检查,因为这些权限是语言特性,仅仅会被编译器进行检查,确保符合规范,编译链接后,成为机器代码,这些语言特性也不复存在。

class A
{
public:
   virtual void fun()
   {
       cout<<"A:fun() call"<<endl;
   }


};
class B:public A
{
private:
    void fun()
    {
    cout<<"B:fun() call"<<endl;
    }


};

int main()
{
   A* ptr=new B();  //编译期没有问题
   ptr->fun();

}

这段代码编译期没有问题,因为ptr被视作A类指针,其fun()是pulibc的

同时,在运行期也没有问题!  因为运行期不会在检查是否符合语言规范(也不可能检查)

可以看到,基于虚函数机制,B的private函数被正确调用

 

 

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:C马雯娟 返回首页