C/C++你必须了解的小知识(5)

174 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

1.1.11 说说静态变量什么时候初始化?

参考回答

对于C语言的全局和静态变量,初始化发生在任何代码执行之前,属于编译期初始化。

而C++标准规定:全局或静态对象当且仅当对象首次用到时才进行构造。

答案解析

  1. 作用域:C++里作用域可分为6种:全局,局部,类,语句,命名空间和文件作用域。

    静态全局变量 :全局作用域+文件作用域,所以无法在其他文件中使用。

    静态局部变量 :局部作用域,只被初始化一次,直到程序结束。

    类静态成员变量:类作用域。

  2. 所在空间:都在静态存储区。因为静态变量都在静态存储区,所以下次调用函数的时候还是能取到原来的值。

  3. 生命周期:静态全局变量、静态局部变量都在静态存储区,直到程序结束才会回收内存。类静态成员变量在静态存储区,当超出类作用域时回收内存。

1.1.12 nullptr调用成员函数可以吗?为什么?

参考回答

能。

原因:因为在编译时对象就绑定了函数地址,和指针空不空没关系。

答案解析

//给出实例
class animal{
public:
    void sleep(){ cout << "animal sleep" << endl; }
    void breathe(){ cout << "animal breathe haha" << endl; }
};
class fish :public animal{
public:
    void breathe(){ cout << "fish bubble" << endl; }
};
int main(){
    animal *pAn=nullptr;
    pAn->breathe();   // 输出:animal breathe haha
    fish *pFish = nullptr;
    pFish->breathe(); // 输出:fish bubble
    return 0;
}  

原因:因为在编译时对象就绑定了函数地址,和指针空不空没关系。pAn->breathe();编译的时候,函数的地址就和指针pAn绑定了;调用breath(*this), this就等于pAn。由于函数中没有需要解引用this的地方,所以函数运行不会出错,但是若用到this,因为this=nullptr,运行出错。

1.1.13 说说什么是野指针,怎么产生的,如何避免?

参考回答

  1. 概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

  2. 产生原因:释放内存后指针不及时置空(野指针),依然指向了该内存,那么可能出现非法访问的错误。这些我们都要注意避免。

  3. 避免办法:

    (1)初始化置NULL

    (2)申请内存后判空

    (3)指针释放后置NULL

    (4)使用智能指针

答案解析

产生原因:释放内存后指针不及时置空(野指针),依然指向了该内存,那么可能出现非法访问的错误。这些我们都要注意避免。如:

char *p = (char *)malloc(sizeof(char)*100);  
strcpy(p, "Douya");  
free(p);//p所指向的内存被释放,但是p所指的地址仍然不变  
...  
if (p != NULL){//没有起到防错作用  
    strcpy(p, "hello, Douya!");//出错  
}  

避免办法:

(1)初始化置NULL

(2)申请内存后判空

(3)指针释放后置NULL

int *p = NULL; //初始化置NULL
p = (int *)malloc(sizeof(int)*n); //申请n个int内存空间  
assert(p != NULL); //判空,防错设计
p = (int *) realloc(p, 25);//重新分配内存, p 所指向的内存块会被释放并分配一个新的内存地址
free(p);  
p = NULL; //释放后置空

int *p1 = NULL; //初始化置NULL
p1 = (int *)calloc(n, sizeof(int)); //申请n个int内存空间同时初始化为0 
assert(p1 != NULL); //判空,防错设计
free(p1);  
p1 = NULL; //释放后置空

int *p2 = NULL; //初始化置NULL
p2 = new int[n]; //申请n个int内存空间  
assert(p2 != NULL); //判空,防错设计
delete []p2;  
p2 = nullptr; //释放后置空