若是全局数组,则会被创建在静态存储区;其他情况会被分配在栈上。
指针数组本质上是数组,每个数组元素指向一个int型变量的地址,数组占多少个字节由数组本身决定。
数组指针本质上是指针,是一个指向一个数组的指针变量,32位系统下永远占4个字节。
vector和数组类似,拥有一段连续的内存空间,并且起始地址不变。其能高效的进行随机存取,时间复杂度为o(1);但因为内存空间是连续的,所以在进行插入和删除操作时,会造成内存块的拷贝,时间复杂度为o(n)。另外,当数组中内存空间不够时,会重新申请一块内存空间并进行内存拷贝。
list由双向链表实现的,因此内存空间是不连续的,且开销较大因为需要额外的指针信息。由于只能通过指针访问数据,所以list的随机存取非常没有效率,时间复杂度为o(n);但由于链表的特点,其能O(1)地进行插入和删除。
在操作系统中,系统会给每个进程分配虚拟地址,虚拟地址的大小与处理器的位数有关,如32位处理器进程可分配4GB的虚拟内存供程序正常运行。这4GB的虚拟内存,存储单元从地址0开始进行排序,此地址为虚拟地址。
该虚拟地址可分为五个部分:
(1)栈区:由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。线程也有自己维护的栈。
(2)堆区:程序动态申请的空间,由程序释放或其他方式释放,若没有释放,可能导致内存泄露。
(3)全局区(静态区):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后有系统释放 。
(4)文字常量区:常量字符串就是放在这里的,程序结束后由系统释放。
(5)程序代码区:存放函数体的二进制代码。
三次握手过程理解
(1)第一次握手:建立连接时,客户端发送syn包(seq=j)到服务器,并进入SYN_SENT状态,等待服务器确认。
(2)第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(seq=k),即SYN+ACK包,此时服务器进入SYN_RECV状态。
(3)第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手
四次挥手过程理解
(1)第一次挥手:客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u,此时,客户端进入FIN-WAIT-1(终止等待1)状态。
(2)第二次挥手:服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
(3)第三次挥手:服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
(4)第四次挥手:客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB(传输控制块)后,才进入CLOSED状态。而服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
有,在本地硬盘的hosts的文件里。
hosts文件:由操作系统操作的IP和域名的本地映射文件,可以视为DNS server的重写,一旦查到了指定的域名,就不会继续查找DNS server,所以可以节省时间。但是hosts设置的IP地址是静态的,如果web app的宿主机地址发生改变,对应的hosts也要改写。
DNS解析查询的详细过程
(1)首先浏览器先检查本地hosts文件是否有这个网址映射关系,如果有就调用这个IP地址映射,完成域名解析。
(2)如果没找到则会查找本地DNS解析器缓存,如果查找到则返回。如果还是没有找到则会查找本地DNS服务器,如果查找到则返回。此过程是递归查询。
(3)如果没有,本地DNS服务器还要向DNS根服务器进行查询。此过程是迭代查询,按根域服务器->顶级域(.com)->第二层域(baidu.com)->子域。
一般而言,我们的代码是这样的:
void swap(int& a, int& b) {
int tmp = a;
a = b;
b = tmp;
}这是因为在 语句执行中,只能进行这一次值的转移,转移过后变量 原来的值就丢失了。所以需要一个辅助变量 暂存 的值。同理,我们还可以利用临时变量暂存 的值,并在一次值转移后通过暂存的两数之和以及已经改变了存储值的一个数相减得到另一个数:
void swap2(int& a, int& b) {
int tmp = a + b;
a = b;
b = tmp - a;
}我们可以进一步地利用 代替 实现这一功能:
void swap3(int& a, int& b) {
b = a + b;
// 现在 b = sum{a, b}
a = b - a;
// a = sum{a, b} - a = b
// 此时 a 中存放的是原来 b 的值
b = b - a;
// b = sum{a, b} - b = a
// 此时 b 中存放的是原来 a 的值
}