C++存储类型

来源:互联网 发布:装饰装修施工资质 知乎 编辑:程序博客网 时间:2024/06/05 18:30

前段时间查到这方面的东西,看这里讲的不错,就翻译了,第一次尝试 :)

原文地址:http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=28

 

 

内存管理

         C++中,一种存储类别(storageclass)定义了某个标志符的内存属性。同样它也决定了一个对象的内存生存期(storage duration):  自动存储生存期(automaticstorage duration)线程存储生存期(thread storage duration),静态存储生存期(staticstorage duration)和空闲内存(free store)。每种存储类别规定了不同的内存使用限制,并表示不同的初始化,生命生存期,作用域和链接语义。决定一个标志符存储生存期的因素有:

 

1>    出现在标志符声明前面的存储类型说明符(e.g., static, thread_local, extern, register)

2>    上下文(比如说,定义在命名空间里的用户定义类型以及函数的参数)

3>    标识符类型(一个函数,一个数据成员等等)

 

下面的章节将解释不同C++存储生存期的区别,讨论他们的使用并列举他们在C,旧标准C++C++09之间的区别。

 

自动存储

         内存生存期是对象的一个属性,它定义了这个对象在内存中的最小生存时间。内存生存期由创建对象的构造函数决定,包括存储类型标志符。最常见的存储生存期是自动存储生存期。因为在堆栈上分配的对象是自动分配和自动释放的,所以具有自动存储生存期。下面的对象具有自动存储属性:

 

1>    没有被显式声明为static, extern 或者 thread_local的局部变量

2>    声明带有auto存储说明符的局部变量(适用C的所有版本和除了C++09之外的C++版本)

3>    声明带有register存储说明符的对象

4>    函数参数

5>    临时对象

 

存储类型标志符

         不要混淆了存储生存期与存储类型标志符。C++09存储类型标志符有:

1>    register

2>    static

3>    thread_local

4>    extern

5>    mutable

 

C++09之前的存储类型说明符列表有点不同:

 

1>    register

2>    static

3>    auto

4>    extern

5>    mutable

 

C语言中,存储类型说明符有:

 

1>    register

2>    static

3>    auto

4>    extern

 

自动存储生存期

         下面的代码包括了自动存储生存期类型的不同声明,对象和变量。

  

 

 

         自动存储生存期类型的对象,简称自动对象,是在进入一个块或一个函数时自动创建的。当程序退出他们所声明的块或者函数时,他们就会被销毁,并且其内存会被自动回收。因此,在一个函数或者块的入口处会创建其自动对象。自动对象和非类对象的默认值都是不确定的。自动对象不可链接,不能从不同的编译单元(translation unit)引用自动对象,并且他们只能在声明的作用域内可见。

         C++09标准不再将auto视为一个内存类型标志符。因此,在C++09的代码里不能使用auto来指定自动内存生存期。因而C++09中自动存储生存期隐藏于上下文中。auto关键字在C++09中仍然存在,但是意义已经改变,所以程序员必须小心:使用了auto作为存储类型的旧版CC++代码编译会出错。

 

Register存储类型标志符

         Register存储类型标志符仅被用来修饰块中声明的对象或者函数参数。声明一个带有register标志符的对象暗示存取此对象会尽可能的快。例如,在一个双重循环里声明一个register类型的计数器可能会被存储在CPUregister里而不是内存里。类似地,一个声明成register类型的类对象可能会被存储到cache里以便快速存取。这种register请求的有效性从某种程度上与实现相关。现在,C或者C++里已经几乎不使用register类型了。大部分编译器不会理会用户的register变量和对象的请求。相反,编译器会自动做出register类型的选择。ISO C规定用户不能获得register对象的地址。在C++中可以这么做,但是这样会使register类型请求失效(对象将被存到内存中)。在其他所有方面(如初始化,生命生存期,作用域)带有register存储类型的对象和自动对象具有同样的语义。


Mutable存储类型标志符

         Mutable标志符修饰一个const类数据成员会使其const属性无效并且会允许更改mutable类型的类数据成员,尽管对象中其余的成员都是const类型的。换句话说,就算是const对象,其mutable成员通常是可以改变的。

 

 

         mutable标志符只能被用在类数据成员的名字前,并且不能和const或者static同时使用,也不能用来修饰引用变量。

例如

 

 

         成员p的声明中,mutable标志符修饰指针,而const标志符修饰被指针指向的int数据。反之,q的声明则是无效的,因为指针被同时声明为constmutable了。类似地,引用变量r的声明是无效的,因为引用变量不可变。

 

静态存储生存期和线程存储生存期

         全局对象和在namespace作用域中的对象,类的静态数据成员,以及函数中驻留在静态存储区的局部静态对象。一个带有静态存储生存期属性的对象在程序的整个执行期间都会驻留在相同的内存中。每一个这种对象在程序的生命生存期内只创建一次。静态数据默认全部被初始化为0。带有一个自定义构造函数或者一个显式动态初始器的静态对象都将经历一个二次初始化阶段,我们称之为动态初始化。

 

         在一个函数中声明的对象,其作用域就被限制在那个函数中。下面的例子中有些静态存储的对象:

 

extern存储类型标志符

         extern标志符只能用来修饰对象和函数。extern标志符不能被用在类成员或者函数参数的声明中。声明成extern的标识符具有外部链接性,意味着他们在同一个程序的所有编译单元中都是可见的。

         namespace作用域中声明的不带存储类型标志符的名称具有外部链接性,除非其由于被声明过而已经具有内部链接性,或者被声明为const类型。被声明为const类型的对象和未被显式声明为extern的对象具有内部链接性,意味着他们只在他们所声明的编译单元内可见。

         注意extern关键字还可以用在别处,他也可以被用在模板的实现初始化和链接标识中,但是此时extern已经不再是一个存储类型标志符。

 

thread_local存储生存期

         thread_local标志符表明其修饰的对象或者引用具有线程存储生存期。thread_local只能用来修饰命名空间中的对象或者引用的名字,以及块作用域中已经被指定为static存储类型的对象和引用。thread_local存储类型是C++09中的新特征。在此不详细讨论。

 

 

原创粉丝点击