当前位置: 移动技术网 > IT编程>开发语言>C/C++ > c++存储持续性、作用域和链接性

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

2018年09月13日  | 移动技术网IT编程  | 我要评论

东阿吧,娄艺潇三围,春哥经

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

●自动存储持续性:

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

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

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

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

●静态存储持续性:

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

☉链接性:

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

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

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

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

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

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

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

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

●动态存储持续性:

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

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

文件结构:

\

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;
}
运行结果:

\

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网