欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

c++存储持续性、作用域和链接性

程序员文章站 2022-03-23 19:36:08
1.c++使用三种不同的方案进行数据的存储,这些方案的区别就在于数据保留在内存中的时间 ●自动存储持续性: 在函数定义中声明的变量(包括函数参数)的存储持续性为自动类型。 ☉作用域:局部,在包含定义...

1.c++使用三种不同的方案进行数据的存储,这些方案的区别就在于数据保留在内存中的时间

●自动存储持续性:

在函数定义中声明的变量(包括函数参数)的存储持续性为自动类型。

☉作用域:局部,在包含定义它的函数内部有效。

☉链接性:没有链接性,只能在定义它的函数内部使用,不能在其他函数中使用。

☉内存对自动类型变量的管理:常用的方法是留出一段内存,并将其视为栈,以管理变量的增减。

●静态存储持续性:

在函数定义外定义的变量和使用static关键字定义的变量为静态类型。

☉链接性:

▼外部链接性:变量定义在函数定义之外,并且没有用static修饰。

作用域:整个程序,可以在各个文件中使用该变量。

▼内部链接性:变量定义在函数定义之外,但是用static修饰。

作用域:在包含这个变量定义的文件的函数中可用。但在其他文件的函数中不可用

▼无链接性:变量定义在函数定义之内,用static休息,与auto的差别在于static修饰的

变量一直存在在内存中,而auto类型的变量使用完后就在内存中销毁了。

作用域:只在变量定义的函数体内有效。

☉内存对静态存储类型变量的管理:由于静态变量的数目在程序运行期间是不变的,因此编译器将分配固定的内存 单元来存储所有的静态变量,这些变量在整个程序执行期间一直存在。

●动态存储持续性:

使用new分配的内存将一直存在,直到使用delete将其释放或函数结束。

2.auto变量,静态变量举例:

文件结构:

c++存储持续性、作用域和链接性

file1.cpp源代码:

#include 
using namespace std;

int error = 3;   //外部变量,在file1.cpp和file2.cpp中都可以使用
static int count = 9;  //静态变量,在file1中可以使用,在file2中不能使用

int myfun();
int fun();

int main()
{
    int num = 5;   //auto类型变量,仅在main函数中能够使用,无链接性
    cout << count << endl; //可以使用
    cout << num << endl;
    return 0;
}

int fun()
{
    cout << count << endl;  //可以使用count,因为count有内部链接性
    cout << error << endl;  //可以使用
    //cout << num << endl;  //不能使用,因为num是在main中定义,无链接性
    return 0;
}
file2.cpp源代码:
#include 
using namespace std;

extern int error;
//extern static int count;   //不能用,因为count是file1.cpp中定义的只具有内部链接性的变量,只能在file1.cpp中使用,不具有外部链接性

int myfun()
{
    cout << error << endl;
    return 0;
}

3.mutable的使用

作用:可以用它来指出,即使结构体(或类)变量为const,用mutable关键字修饰的变量的值也是可以改变的。

举例:

struct data
{
    char name[30];
    mutable int level;
};

const data veep = {"zhangfei", 1};
veep.level++;  //这句是有效的,虽然veep被定义为const,但是level成员前有mutable修饰,所以可以修改

4.在c++中,被const修饰的全局变量的链接性为内部链接

如:

const int fingers = 10;
int main()
{
   ...
}
fingers这个变量只能在该文件中使用,不能在该项目的其他文件中使用。

5.函数和链接性:

●所有函数都是静态的,即整个程序的执行期间一直存在

●在默认情况下,函数的链接性为外部链接,即可以在文件间共享

●可以使用关键字static将函数的链接性设置为内部链接,即只能在一个文件中使用,在函数声明和函数定以前都要加上static

static int private(double x);
...
static int private(double x)
{
  ...
}

●单定义规则也适用于非内联函数,内联函数不接受这条规则的约束,这允许程序员能够将内联函数的定义放在头文件中

6.定位new运算符

通常,new运算符负责在堆中找到一个足以能够满足要求的内存块。new运算符还有另外一种变体,能够指定要使用的位置,被称为定位new运算符。要使用定位new运算符,需要包含头文件new。需要注意的是,delete只能用于删除指向常规new运算符分配的堆内存。

常规new运算符和定位new运算符举例:

#include 
#include           //要使用定位new运算符,需要包含头文件new
using namespace std;

const int n = 5;
const int buf = 512;
int buffer[buf];

int main()
{
    int *pi1, *pi2, *pi3, *pi4;
    pi1 = new int[buf];           //pi1在内存中找一块能使用的内存,位置不定
    pi2 = new (buffer) int[buf];  //pi2使用定位new,所分的内存是从buffer开始
    cout << "calling new and placement new:\n";
    cout << "memory addresses:\n";
    cout << "  heap: " << pi1 << "  static: " << pi2 << endl;
    cout << "memory contents:\n";
    for(int i = 0; i < n; i++)
        pi1[i] = pi2[i] = 1000 + 20 * i;
    for(int i = 0; i < n; i++)
    {
        cout << pi1[i] << " at " << &pi1[i] << "  ";
        cout << pi2[i] << " at " << &pi2[i] << endl;
    }

    cout << endl;
    cout << "calling new and placement new a second time:\n";
    cout << "memory contents:\n";
    pi3 = new int[buf];           //pi3在内存中找一块能使用的内存,位置不定
    pi4 = new (buffer) int[buf]; //pi4使用定位new,所分的内存是从buffer开始,所以pi4显示的地址跟pi2一致
    for(int i = 0; i < n; i++)
        pi3[i] = pi4[i] = 1000+ 40 * i;
    for(int i = 0; i < n; i++)
    {
        cout << pi3[i] << " at " << &pi3[i] << "  ";
        cout << pi4[i] << " at " << &pi4[i] << endl;
    }

    delete [] pi1;
    delete [] pi3;         //释放常规new分配的内存,定位new分配的内存不能使用delete
    return 0;
}
运行结果:

c++存储持续性、作用域和链接性