目录
7. 关键字define、const、typedef、inline
1. 智能指针
优点
(1)避免内存泄漏。底层维护一个类,作用域结束可以自动释放内存。
(2)共享指针便于传播和释放。例如多线程使用同一个对象时析构问题。
auto_ptr
(c++98用,c++11已放弃)。如下,p2剥夺了p1所有权,访问p1会报错。
auto_ptr<std::string> p1 (new string ("hello"));
auto_ptr<std::string> p2;
p2 = p1;
unique_ptr
独占所有权的指针,即同一时间只能有一个std::unique_ptr指向同一个对象。如下,P4 = P3会报错,因为P3不能再指向有效数据。
unique_ptr<string> p3 (new string (auto));
unique_ptr<string> p4;
p4 = p3;
shared_ptr
共享所有权的指针,即可以有多个std::shared_ptr指向同一个对象。有两个指针,一个指向堆内存中的对象,另一个指向共享实例的引用计数器。
引用计数器
- 每次调用shared_ptr的复制构造函数时,引用计数器+1。
- 每次调用shared_ptr的赋值运算符时,右侧指针计数器+1,左侧指针计数器-1。
- 每次调用shared_ptr的析构函数时,计数器均-1。
- 计数器为0时,删除该对象。
weak_ptr
弱引用指针,即一个std::weak_ptr指向一个std::shared_ptr所管理的对象,但不会增加引用计数。
2. 内存分配
栈:存放局部变量和函数参数,编译器管理内存分配和回收。
堆:程序员管理,手动new/delete或malloc/free,容易造成内存泄漏。
全局、静态存储区:存储初始化/未初始化的全局变量和静态变量,有初始化和未初始化两个区域。
代码区:存放二进制代码。
一维数组动态分配释放代码示例:
// 动态分配,数组长度为 m
int *array=new int [m];
//释放内存
delete [] array;
二维数组动态分配释放代码示例:
int **array;
array = new int *[m];
for(int i = 0; i < m; i++ ) {
array[i] = new int [n];
}
//释放
for(int i = 0; i < m; i++ ) {
delete [] array[i];
}
delete [] array;
对象动态分配释放代码示例:
#include <iostream>
using namespace std;
class Box {
public:
Box() {
cout << "调用构造函数!" <<endl;
}
~Box() {
cout << "调用析构函数!" <<endl;
}
};
int main( )
{
Box* myBoxArray = new Box[4];
delete [] myBoxArray;
return 0;
}
3. 指针参数传递和引用参数传递
指针参数传递
本质是值传递,传递的是一个地址值,传递过程中,被调函数的形参作为被调函数的局部变量处理,在栈开辟空间存放有主调函数传递来的实参,从而形成实参副本。特点:被调函数对形参指针改变不影响主函数实参指针。
引用参数传递
被调函数形参也作为局部变量在栈中开辟了内存空间,存放的是主调函数放进来的实参变量的地址。特点:被调函数对形参指针改变会被处理成间接寻址,即通过栈中存储的地址找到实参,因此,被调函数对形参指针改变会影响主函数实参指针。
4. 关键字static
修饰局部变量
局部变量一般存储于栈,static修饰的局部变量存储于静态数据区,生命周期会一直延续到整个程序结束,作用域未变还是在其语句块。
修饰全局变量
static修饰的全