程序拥有:1.静态内存;2.栈内存;3.自由空间 / 堆(储存动态分配的对象)
一. new 与 delete 运算符
1.new 运算符
1).动态分配内存
new 表达式在自由空间构造一个 int 型(无名)对象,并返回该对象的指针:
int *pi = new int;
2).初始化对象
a.未显式初始化:默认初始化:内置类型或组合类型的值是未定义的,类类型用默认构造函数初始化;
int *pi = new int; //pi指向一个未定义的int
string *ps = new string; // ps指向一个空 string(默认构造函数)
内置类型:算术类型(bool, char, int, float, double)和空类型(空类型不对应具体的值,仅用于一些特殊的场合,如当函数不返回任何值时使用空类型(void)作为返回类型);
组合类型:引用、指针、数组;
b.显式初始化:直接初始化(与拷贝初始化区分):可以使用:
(1).传统构造方式(圆括号)
(2).列表初始化(花括号)或者值初始化
int *pi = new int(1024);
vector<int> *pv = new vector<int>{0, 1, 2};
int *pi1 = new int(); // 值初始化为0,*pi1的值为0
(3).使用 auto 和初始化器
auto p1 = new auto(obj); // obj 是一个某类型的对象,p1指向从 obj 推断出的类型;
3).动态分配 const 对象
const int *pci = new const int(1024);
const string *pcs = new const string; //默认初始化
a. const 对象必须初始化,对于一个定义了默认构造函数的类类型,可以隐式初始化;
b.返回一个指向 const 的指针;
4).内存耗尽
int *p1 = new int; //默认情况下,分配内存失败会抛出一个类型为 bad_alloc 的异常
int *p2 = new (nothrow) int; //定位new:向 new 传递名为 nothrow 的对象,这种情况下分配内存失败会返回一个空指针;
2.delete 运算符
1).释放动态内存
delete 表达式执行两个动作:销毁对象+释放内存;
传递给 delete 的指针必须是:(1).用 new 分配内存的指针;(2).空指针;
2).动态对象的生存期直到被释放时为止
void factory(T arg) {
Foo *p = new Foo(arg);
} // p 离开它的作用域,局部变量 p 被销毁,但它所指向的对象什么也不会发生,即此动态内存也不会被释放
3). delete 之后重置指针值
delete 之后,指针(在某些机器上)就变成了空悬指针:指向一块曾经保存数据对象但现在已经无效的内存;
避免空悬指针:在指针离开作用域前释放掉它所关联的内存,若需要保留指针,可以在 delete 之后将 nullptr 赋予指针;
3.动态数组
1).使用 new 和 delete
1.
int *pia = new int[size]; // pia 指向数组首位
2.
typedef int arrT[42];
int *p = new arrT; //使用表示数组类型的类型别名,与以下语句等价:
int *p = new int[42];
分配的内存不是数组类型,不能调用 begin 或 end 函数;
a.初始化数组:
(1).默认初始化
(2).值初始化
(3).元素初始化器的花括号列表
不能用 auto 分配数组;
int *pia = new int[10]; //值未定义
int *pia2 = new int[10](); //值均为0
int *pia3 = new int[10]{0, 1, 2, 3}; //之后的六个值初始化
string *psa = new string[10]; //空 string
string *psa2 = new string[10](); //空 string
string *psa3 = new string[10]{"a", "an"};
b.分配一个空数组是合法的
char arr[0]; //错误
char *cp = new char[0]; //正确,但 cp 不能解引用
c.释放动态数组
delete [] pa; //pa 必须指向一个动态分配的数组或为空指针
元素按逆序销毁,[] 提示编译器此指针指向一个对象数组的第一个元素;
2).智能指针
3). allocator 类
4.题目
1).
class Point {
public:
Point();
Point(int x, int y);
~Point();
int getX() const;
int getY() const;
void move(int newX, int newY);
private:
int x, y;
};
构造函数和 move 成员函数有什么区别:
getX 和 getY 为什么用 const:
~Point 函数是什么意思:
2).
class ArrayOfPoints { //动态数组类
public:
ArrayOfPoints(int size) : size(size) {
points = new Point[size];
}
~ArrayOfPoints() {
cout << "Deleting..." << endl;
delete [] points;
}
Point& element(int index) {
return points[index];
}
private:
Point *points; //指向动态数组首地址
int size; //数组大小
};
~ArrayOfPoints 函数是什么意思:
element 函数为什么用引用:要修改原数组中元素而不是想得到一个副本;
二.智能指针