-
内存模型和名称空间
- 存储持续性,作用域和链接性
C++有三种方案来存储数据- 自动存储持续性:在函数定义中声明的变量,包括函数参数。在函数或代码块开始执行时创建。执行完函数或者代码块,内存自动释放。
- 静态存储持续性:函数定义外定义的变量和使用关键字static定义的变量。他们在程序的整个运行过程中都存在。
- 动态存储持续性:用new分配的内存,要显式使用delte操作符释放或者程序结束,系统程序来释放。
作用域表述变量名称的可见范围。在某一范围内,变量名称不能重复。链接性描述名称如何在不同单元(通常为文件)之间进行共享。链接性为外部,则可多个文件共享。链接性为内部,则只能在一个文件中的函数共享。自动变量无链接性,则不能共享。
自动存储持续性:在默认情况下,函数中声明的函数参数和变量为自动存储持续性。作用域为局部,没有链接性。
静态持续变量有三种链接性:
- 外部链接性:在代码块外面声明它。又称为全局变量。可以多个文件分享数据。但是const 全局常量的链接性为内部链接性。因为变量有且只能有一个文件包含其定义,在其他文件使用时,使用extern关键字进行引用声明。
- 内部链接性:在代码块外面声明它,但是用static修饰。static将链接性限定为本文件,但是可以在本文件的多个函数间分享数据。其他文件用extern声明它时,编译器找不到该变量。本地的static静态变量会隐藏常规外部变量。
- 没有链接性:在代码块内部声明它,但是用static修饰。在整个程序运行期间,其内存一直存在,程序结束才会释放。而且即使函数被调用多次,其初始化语句只会执行一句。
未被初始化的静态变量的所有位都被设置为0。
C++关键字中有一些被称为存储说明符(storage class specifier)和cv-限定符的关键字。他们提供了有关数据(变量)的存储信息。
CV限定符
- const:它表明,内存被初始化后,程序便不能再对它进行修改。所以const常量声明时就必须初始化。但是const全局变量的链接性为内部的。所以可以在头文件中包含常量声明。因为在源代码文件中#include头文件后,其链接性为该文件内部。
- volatile:它修饰变量,表明即使程序代码没有对内存单元进行修改,其内存内容也可能改变。比如两个程序共享数据,指针指向某个硬件,该硬件的数据会自行改变。如果一个变量被连续几个语句使用,编译器一般会优化代码,将该数据取出后放在寄存器中参与运算。最后再一次性写回内存。对volatile变量不会如此。
存储说明符
- auto:将变量声明为自动变量。因为变量默认就为自动变量,一般不用。
- register:指出变量为寄存器存储类型。
- static:将全局变量声明为内部链接性。将局部变量声明为无链接性,且为静态持续。
- extern:表明是引用声明,声明引用在其它地方/文件中定义的变量。编译器见到此声明,去其他文件寻找变量定义。
- mutable:一般修饰结构或者类中的某个成员变量。指出即使结构或类变量为const,其中的某个成员也可以被修改。
函数也有链接性。函数的存储持续性默认为静态,链接性默认为外部,即可跨文件共享。所以在一个工程中参与编译的文件中。函数不可重名。还可以使用static修饰函数,将其链接性设置为一个文件。则不同文件中可以有同名函数。static要同时修饰原型和定义。
- 布局new操作符
- 存储持续性,作用域和链接性
-
对象和类
不必在类中使用关键字private。因为这是类对象的默认访问控制。
C++中的结构和类十分相像,类就像是包含成员函数以及public和private可见性标签的结构声明。实际上,它们之前的惟一区别是,结构的默认访问类型是public,而类是private。可以用类来表示纯粹的数据对象或者没有私有部分的类。
和cout一样,cerr也是一个ostream对象,两者区别在于,操作系统重定向只影响cout,而不影响cerr。所以,如果将程序输出重定向到文件,并且发生了错误,则屏幕上依然会出现错误消息。在UNIX系统中,>用于对cout进行重定向, 2>对cerr进行重定向。
类声明习惯于将短小的成员函数作为内联函数。
- 定义位于类声明中的函数都将自动成为内联函数。
- 也可以在类声明之外定义成员函数。在定义函数时用inline限定符即可。类中函数声明可不使用inline。
- 内联函数要求每个使用他们的文件中都有对其进行定义。所以常将内联定义放在定义类的头文件中。
使用构造函数的两种方式:
- 显式调用构造函数:ClassName classVar = ClassName(...)
- 隐式调用构造函数:ClassName classVar(...);
构造函数是用来创建对象的,因此对象不能调用构造函数。如果程序员没有提供任何构造函数,则C++将自动提供任何构造函数,但是它不做任何工作。但是只要程序员提供构造函数,则C++编译器就不会自动提供默认构造函数。所以,程序员必须自己提供默认构造函数,否则
ClassName classVar;
这样代码会编译错误。定义默认构造函数的两种方式:
- 给已有构造函数的所有参数提供默认值。
- 通过函数重载定义一个没有参数的构造函数。
但是默认构造函数只能有一个,否则会产生二异性。所以上述两种方式只能采用一种。而且在隐式调用默认构造函数时,不要使用()。
Stock stock1(); //这是声明了一个名为stock1,无参数,返回值为Stock的函数
构造函数创建对象,等对象过期时,程序自动调用析构函数用来进行清理工作。最简单的是在构造函数中用new动态申请内存空间,在析构函数中用delete释放内存。
在默认情况下,将一个对象赋值给同类型的另一个对象时,C++将源对象的每个数据成员的内容复制到目标对象中相应的数据成员中。基本数据类型,结构变量,类对象原理一样。