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

一、存储方案
1)自动存储持续性:在函数定义中声明(包括函数参数)的存储持续性为自动的。在开始执行所属函数或代码块时被创建,执行完时被释放。
2)静态存储持续性:在函数定义外的变量和使用关键字static定义的变量。他们在整个运行过程中都存在。
3)线程存储持续性。
4)动态存储持续性:使用new或malloc分配的内存,又被称为自由存储(free store)或堆(heap)。
二、作用域和链接性
作用域:描述了名称在文件(翻译单元)的多大范围可见。
连接性:描述名称如何在不同单元间共享。
三、自动存储持续性
作用域为局部,没有链接性。

int main()
{
    int i = 5;   //main函数中可见
    {
        cout<<  "hello\n";
        int j = -9;   //只在代码块中可见
        int i = 7;   //输出i等于7,隐藏了以前的定义
        cout<< j << " " << i <<endl;
    }
    cout<< i <<endl;   //i等于5
    ......
}

寄存器变量
关键字register:提高访问变量的速度。
在C++11中显示地指出变量时自动的,只能作用于原来就是自动的变量。
四、静态持续变量
1)外部链接性:可在其它文件中访问,必须带代码块外面声明。
2)内部连接性:只能在当前文件中访问,必须在代码块外面声明,并使用static限定符。
3)无连接性:只能在当前函数或代码块中访问,必须在代码块内声明,并使用static限定符。
以上三种都在整个程序执行期间存在。

...
int global = 100;   //外部链接性
static int one_file = 200;  //内部连接性
int main()
{
    ...
}

void funct(int n)
{
    static int count = 123;  //无链接性
    int i = 0;
}

void funct2(int m)
{
...
}

静态变量的初始化:零初始化和常量初始化(意味着编译器处理文件时初始化变量,动态初始化意味着变量在编译后初始化)


int main()
{
    int x; //零初始化
    int y = 15; //常量初始化
    long z = 13 * 13; //常量初始化
    const double pi = 4.0 * atan(1.0); //动态初始化
}

//首先x、y、z、pi被零初始化。然后,编译器计算常量表达式,将y和z被初
//始化为5和169,但要初始化pi,必须调用函数atan(),需要等到该函数被
//链接且程序执行时。

五、静态持续性、外部链接性
外部变量(全局变量):连接性为外部的变量,作用于整个文件。
单定义规则(ODR):变量只能定义一次。C++提供两种变量声明。一种是定义声明简称“定义”,给变量分配存储空间,另外一种引用声明简称“声明”,不给变量分配存储空间,引用已有的变量。
引用声明使用关键字extern,且不进行初始化;否则,声明为定义,导致分配存储空间。
作用域解析运算符(::)。放在变量名前面时,表示该变量用的是全局版本。
六、静态持续性、内部链接性
将static限定符用于作用域为整个文件的变量时,该变量的连接性将为内部的。

//file1
int i = 20;
...
-------------------------------
//file2
static i = 30;
void froobish()
{
    cout<< i <<endl;   //uses i defined in file2
    ...
}

七静态存储持续性、无链接性
该变量值在定义的代码块中可用,但它在该代码块不处于活动状态时仍然存在。两次调用函数之间,静态局部变量的值保持不变。(静态变量适用于再生——将瑞士银行密码账号传递到下一个要去的地方)

#include<iostream>
using namespace std;

const int ArSize = 10;

void strcount(const char * str);

int main()
{
    char input[ArSize];
    char next;

    cout<< "Enter a line:\n" ;
    //一直读取,直到到达行尾或读取了ArSize-1个字符,把换行符留在队列中
    cin.get(input, ArSize); 
    while(cin)
    {
        //读取输入后的字符,如果为换行符说明cin.get(input, ArSize)
        //读取了整行,否则说明没有读取完
        cin.get(next);  
        while(next != '\n') //丢弃余下的字符
            cin.get(next);
        strcount(input);
        cout<< "Enter next line (empt line to quit):\n";
        cin.get(input, ArSize);
    }

    cout<< "Bye\n";

    return 0;
}

void strcount(const char * str)
{
    static int total = 0;   //静态变量(第一次调用时置为0,以后调用时为上次调用后保存的值)
    int count = 0;  //自动变量(每次被调用时都重新置为0)

    cout<< "\"" << str <<"\" contains";
    while(*str++)
        count++;
    total += count;

    cout<< count << "characters\n";
    cout<< total << " characters total\n";
}

八、函数和链接性
C/C++不允许在一个函数中定义另一个函数,因此所有函数的存储持续性都自动为静态的。默认情况下,函数的连接性为外部的,可以在文件间共享。实际上,函数原型可以使用关键字extern指出函数是在另一个文件中定义的。也可以使用关键字static将函数的连接性设置为内部的,只在一个文件中使用,必须原型和函数定义中使用该关键字:

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

九、存储方案和动态分配呢
动态内存:C++运算符new或C函数malloc()分配的内存
1)使用new运算符初始化:

int *pi = new int (6);   //*pi set to 6
double *pi = new double (99.99); //*pi set to 99.99

//C++11
struct where {
    double x;
    double y;
    double z;
    };
where *pi = new where {12.23, 23.34, 34.45};
int * ar = new int [4] {2, 3, 4, 5};
int * pin = new int {6};

2)new失败时 :
引发异常std::bad_alloc.(以前为返回空指针)。
3)new:运算符、函数和替换函数
运算符new和new[]分别调用如下函数:

//分配函数
void * operator new(std::size_t);
void * operator delete(std::size_t);

void * operator new [] (std::size_t);
void * operator delete [] (std::size_t);

//std::size_t是一个typedef,对应合适的整形。

4)定位new运算符
指定要使用的位置。需要包含头文件#include.

#include<iostream>
#include<new>

using namespace std;

const int BUF = 512;
const int N = 5;
char buffer[BUF];

int main()
{
    double *p1, *p2;
    int i;
    cout<< "Calling new and placement new:\n" <<endl;
    p1 = new double[N];             //use heap
    p2 = new (buffer) double[N];    //use buffer array
    for(i = 0; i < N; i++)
        p2[i] = p1[i] = 1000 + 20 * i;
    cout<< "Memory addresses:\n" <<" heap: " << p1
        << " static: " << &buffer <<endl;
    cout<< "Memory contents:\n";
    for(i = 0; i < N; i++)
    {
        cout<< p1[i] << " at " << &p1[i] << "; ";
        cout<< p2[i] << " at " << &p2[i] << endl;
    }

    cout<< "\nCalling new and placement new a second time:\n";
    double *p3, *p4;
    p3 = new double[N];
    p4 = new (buffer) double[N];
    for(i = 0; i < N; i++)
        p4[i] = p3[i] = 1000 + 40 * i;
    cout<< "Memory contents:\n";
    for(i = 0; i < N; i++)
    {
        cout<< p3[i] << " at " << &p3[i] << "; ";
        cout<< p4[i] << " at " << &p4[i] << " --- "
            << p2[i] << " at " << &p2[i] <<endl;
    }

    cout<< "\nCalling new and placement new a thrid time:\n";
    delete [] p1;
    //delete [] p2;
    p1 = new double[N];
    //从数组buffer开头算起的偏移量
    p2 = new (buffer + N * sizeof(double)) double[N];   
    for(i = 0; i < N; i++)
        p2[i] = p1[i] = 1000 + 60 * i;
    cout<< "Memory contents:\n";
    for(i = 0; i < N; i++)
    {
        cout<< p1[i] << " at " << &p1[i] << "; ";
        cout<< p2[i] << " at " << &p2[i] << endl;
    }
    delete [] p1;
    delete [] p3;


    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值