C++学习笔记:存储持续性、作用域、链接性【C++ Primer plus】

在C++有4种数据在内存存储的时间类型【本菜只讲3种】

1:自动存储时间持续性:这个很好理解,就是你在某个函数中声明一个变量【注意:不是静态的】,那么这个函数的生命周期是从函数开始到函数结束,即在函数开始时,系统按照程序声明一个变量A,当函数结束时,系统会把这个变量清除;

这里可能有些人会有疑惑,看以下代码:

#include<iostream>
#include<cstring>

const char *get(const char *q) {

	return q;

}

int main() {

	const char *p;

	p = get("Hello World");

	std::cout << p;

}

get函数是返回一个指向一个字符串的指针,但是根据我们上面说的,q在get函数结束时就已经被清理了,那怎么返回呢?本菜面前知道有两种解释,都是来自C++ Primer Plus这本书的;

1:将变量赋值给一个无名中间变量,然后返回无名中间变量;

2:当返回的是指针时,p指向的内存会重新使用;

这种变量是放在栈中的,我们知道,栈是一个先进后出的一个数据结构,当程序居然函数A时,有两个指针指向栈顶和栈低,它先定义一个变量a,然后将a放入,栈顶向后移动,然后定义一个变量b,栈顶仍然向后移动,如果后面仍然出现如此情况,那么依然是栈顶向后移动,然后函数结束,栈顶会回到初始时的位置,但其他内存当中的二进制不会改变,当下次有变量时直接覆盖即可;


2:静态存储时间持续性:这个好理解,这种变量有一个特性,就是生命周期于程序一样长,当程序停止时这个变量才会被释放,声明这种变量有两种方式:

1:用static关键字;

2:在函数外面定义变量;

这种变量因为是于程序的生命周期一样长,所以系统不会将其放入栈和堆中,程序会将其放入一个特定的地址当中,当程序结束时,这些变量会被清除;


3:动态存储时间持续性:这里一般是用new和delete函数来首先动态存储的管理,new创建空间,delete清除变量;

new和delete管理的是一个内存池,也叫自由存储区和堆。因为这个堆是于栈和静态存储空间是分离的,所以系统跟踪起来也变得麻烦;

这里来讲一个关于new和delete的使用注意:

要注意,如果我们在函数中定义一个用new创建局部指针变量,这个指针指向的实例会放到堆当中【要注意,动态存储的是实例,而不是指针,所以指针是一个自动存储的变量】,然后函数结束时指针变量被撤销,如果在这之前,指针指向的实例没有用delete撤销,那么会出现一种极其可怕的现象,那就是内存泄漏,就像你去钓鱼一样,你掉到一半,鱼竿段了,这个时候你要去找鱼竿就是大海捞针——不可能了,而且鱼竿的材料也会对湖泊造成污染;

对内存当中也是一样,当你指针被清除,但是指向的实例是一个无名实例,那么系统就无法联系这块内存,且系统依然认为这里存储着数据,并不会对这块内存进行重新利用,直到程序结束,这种东西对于运行时间短,new次数少的程序无伤大雅,但是对于运行时间长,new次数多的程序就是个致命伤了;


下面开始讲作用域了:

作用域说白了就是一个变量、类、函数在哪些范围是可见的,哪些范围是不可见的,而C++对这些东西进行了规定;

1:自动变量的作用域,自动变量上面说了,是一种存储在栈中的变量,所以它的作用域是代码块,即一对花括号的范围;

2:函数内的静态变量的作用域:如果我们在函数中定义一个静态变量,这就比较有趣了,这相当于我们创建的变量是不在堆中的,而是在静态变量区的,所以函数结束时栈顶回到初始位置时的操作不会影响静态变量,我们看以下代码:

#include<iostream>
#include<cstring>

void add(){

	static int sum = 0;

	sum++;
	std::cout << sum << ' ';
}

int main() {

	for (int i = 1; i <= 100; i++)
		add();

}

这里如果sum是自动变量的话,那么sum每次输出当然都是1,但是这是sum变量,所以它不会因为add函数结束而被清除,所以每次调用add函数,sum都会在原有的基础上+1,所以输出为如下:

 但是要知道,静态变量只会定义一次,即系统只有在第一次记入add函数时,系统才会分配空间,其它记入add时,则不会重新定义。因为在函数中定义静态变量,所以该静态变量的作用域是函数内部;

当然,我们也可以在函数外面定义静态变量,但是要特别注意,在函数外的static和函数内的static有完全不同的含义【类中的static相对这两个也有不同的含义,所以static的含义是要根据系统根据上下文来推断】,在函数外部,外面只要像在函数内步声明一个自动变量一样声明一个变量即可声明一个静态变量,所以在函数外面系统不需要static来声明一个静态变量,那么static自然而然也被赋予其它含义,即如果外面用static声明一个在函数外面,我们是限制了这个变量的作用域,即这个变量只能被本文件被使用;【如果要看static在类当中的作用,那么可以去翻一下我原先的文章】


然后是链接性;

这个东西和作用域是有一定关系的,怎么说呢?链接性就是看你这个变量或者函数能否被其他文件调用,如果能,那就是是有链接性的变量,如果不能,就是无链接性的变量;

上面说的用static定义函数外的变量,其实就是改变了该变量的链接性。如果是在函数外,且非static变量,那么就是有链接性【因为其他文件可以通过extern关键字来调用该变量】。如果是函数外,且static变量,则只能在本文件调用,其他文件通过extern不能调用该变量或者函数,即无链接性。如果是在函数中定义的,那么无论是不是static,但是无链接性的;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值