本章通过问答方式明晰两个关键字及其作用。

Q1:对于int x;,不加extern关键字他就是个未赋初值的定义,但是如果加了static或者extern都可以表示这仅是一个声明吗?

A:不是的,具体情况如下:

int x; 是一个定义,它为 x 分配了存储空间,但没有显式地初始化。如果 x 是全局变量或静态变量,它会被隐式初始化为0。类内或函数内局部变量是一个随机数,尽量避免这种情况;

extern int x; 是一个声明,它告诉编译器 x 是一个整型变量,但并未为其分配存储空间。你需要在其他地方定义 x。

static int x; 可以是声明或定义,具体取决于上下文。如果它出现在函数内部,那么它是一个定义,并且 x 只能在该函数内部访问。如果它出现在全局范围内,那么它是一个定义,并且 x 只能在当前文件内访问。如果它出现在类内部,那么它是一个声明,并且你需要在类外定义并初始化这个静态成员变量。

Q2:static是可以用来标记本文件作用域的吗?

A: 是的,对于extern关键字,它可以通过extern int x;说明x在其他文件中已定义,请到其他地方寻找,但如果同时赋值,那么extern关键字的作用就被抵消了,如extern int x = 1等价于int x = 1;

而对于static int x;说明x仅在本文件中定义,其他文件无法访问。

Q3:为什么类内的static只是一个声明,定义和赋初值都需要在类外实现?

A:

1.根据primer第4版的解释,static局部对象必须遵守[确保不迟于在程序执行流程第一次经过该对象的定义语句时进行初始化]的这一个原则。

2、同时,我们知道类内部的执行顺序并不是按行次序执行的,而是按对象调用执行的

3、以上两者决定了一个问题: 如果在类内定义,那么不建立对象时,静态数据成员无法初始化,或初始化时间太迟。(可能原因之一]

4、再者,静态成员的生命周期是,一经建立便会存在与整个程序的生命周期内。而静态数据成员即属于类、也不属于类的原因便在此,在类内定义,会使其完全成为该类中的成员,也就是说,当建立复数人该类对象时,会再次声明并定义这静态变量的位置,且名字空间和作用域相同下,导致重名问题。(可能原因之二)

5、因此static的成员需要独立于类作定义

Q4:函数内定义的static变量出了函数作用域后还会存在吗?

A:

是的,函数内定义的静态变量在函数执行完毕后仍然存在。静态变量在程序执行期间只被初始化一次,并且它们的生命周期与程序的生命周期相同。这意味着,即使函数执行完毕,静态变量仍然存在,并且在下一次调用该函数时,它们将保留上一次调用时的值。

例如,下面这个函数 count 使用了一个静态变量 x 来记录它被调用的次数:

void count() {
static int x = 0;
x++;
cout << x << endl;
}

每次调用 count 函数时,x 的值都会增加1,并输出当前的值。即使函数执行完毕,x 仍然存在,并且在下一次调用 count 函数时,它将保留上一次调用时的值。即static int x = 0;只会在第一次调用count()函数时起效一次。

详解C++中的extern与static关键字的更多相关文章

  1. 从缓存入门到并发编程三要素详解 Java中 volatile 、final 等关键字解析案例

    引入高速缓存概念 在计算机在执行程序时,以指令为单位来执行,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入. 由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这 ...

  2. 【转】详解C#中的反射

    原帖链接点这里:详解C#中的反射   反射(Reflection) 2008年01月02日 星期三 11:21 两个现实中的例子: 1.B超:大家体检的时候大概都做过B超吧,B超可以透过肚皮探测到你内 ...

  3. 详解Webwork中Action 调用的方法

    详解Webwork中Action 调用的方法 从三方面介绍webwork action调用相关知识: 1.Webwork 获取和包装 web 参数 2.这部分框架类关系 3.DefaultAction ...

  4. 详解Java中的clone方法

    详解Java中的clone方法 参考:http://blog.csdn.net/zhangjg_blog/article/details/18369201/ 所谓的复制对象,首先要分配一个和源对象同样 ...

  5. 详解Python中re.sub--转载

    [背景] Python中的正则表达式方面的功能,很强大. 其中就包括re.sub,实现正则的替换. 功能很强大,所以导致用法稍微有点复杂. 所以当遇到稍微复杂的用法时候,就容易犯错. 所以此处,总结一 ...

  6. jQuery:详解jQuery中的事件(二)

    上一篇讲到jQuery中的事件,深入学习了加载DOM和事件绑定的相关知识,这篇主要深入讨论jQuery事件中的合成事件.事件冒泡和事件移除等内容. 接上篇jQuery:详解jQuery中的事件(一) ...

  7. 图文详解Unity3D中Material的Tiling和Offset是怎么回事

    图文详解Unity3D中Material的Tiling和Offset是怎么回事 Tiling和Offset概述 Tiling表示UV坐标的缩放倍数,Offset表示UV坐标的起始位置. 这样说当然是隔 ...

  8. 【转】详解JavaScript中的this

    ref:http://blog.jobbole.com/39305/ 来源:foocoder 详解JavaScript中的this JavaScript中的this总是让人迷惑,应该是js众所周知的坑 ...

  9. 深入详解SQL中的Null

    深入详解SQL中的Null NULL 在计算机和编程世界中表示的是未知,不确定.虽然中文翻译为 “空”, 但此空(null)非彼空(empty). Null表示的是一种未知状态,未来状态,比如小明兜里 ...

  10. java 乱码详解_jsp中pageEncoding、charset=UTF -8"、request.setCharacterEncoding("UTF-8")

    http://blog.csdn.net/qinysong/article/details/1179480 java 乱码详解__jsp中pageEncoding.charset=UTF -8&quo ...

随机推荐

  1. api接口基础Day1

    精华笔记: String: String的常用方法: length():获取字符串的长度(字符个数) trim():去除当前字符串两边的空白字符 toUpperCase()/toLowerCase() ...

  2. 【vue】数据代理

    Object.defineProperty()方法 我们先来看几段代码 常用添加属性的方法,以添加age举例 ,点击查看代码 let person = { name: '张三', sex: '男', ...

  3. @DeclareParents声明对象的AOP

    今天在使用@DeclareParents时,使用AspectJ拓展对象的接口 public interface Encoreable { void nextPerformance(); } @Comp ...

  4. CBV源码分析及模板语法之传值 过滤器 标签 继承 导入

    CBV的源码分析 # CBV的源码入口从哪里看呢? CBV的核心源码: return self.dispatch(request, *args, **kwargs) def dispatch(self ...

  5. HTTP 认证授权技术归纳

    原文:https://coolshell.cn/articles/19395.html

  6. git merge的原理

    当我我们拉去代码合并到master的另一个分支上面去的时候 只是对比当前分支commit的修改与增加的代码,其他代码以master为主.

  7. 《Unix/Linux系统编程》第十二周学习笔记

    <Unix/Linux系统编程>第十二周学习笔记 MySQL数据库简介 MySQL是一个关系型数据库管理系统,是最流行的关系型数据库管理系统之一.在 WEB 应用方面,MySQL 是最好的 ...

  8. POI设置单元格下拉框

    一.导出 Excel 单元格设置下拉框 日常开发中,导出基础数据为模版,填充信息后导入时,有时候会要求某些导入项应该为下拉框选择,一个是为了规范数据,也可以简化填充. 1.1 单元格下拉框选项总字符较 ...

  9. ACM 的正确入门方式是什么?

    作者:数学lover 链接:https://www.zhihu.com/question/51727516/answer/127265733 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权, ...

  10. rosdep初始化顺利进行

    rosdep初始化顺利进行 rosdep初始化需要两条命令 sudo rosdep init rosdep update 但在国内,我们通常会出现因为网络状况访问服务器超时的问题 解决方案就是将资源手 ...