OSX + Xcode + C++ (13)

动态内存分配

我们前面学习了数组的声明和定义,语法为

data_type array_name[array_size] = {elements}; 

也就是说,无论在声明中,还是在初始化中,必须有一方给出数组的大小。
那么对于数组大小不确定的情况下,使用这种方式就会出现问题。因此,c++提供了动态内存分配的机制来解决变量个数不确定时内存空间的分配问题。

动态申请内存操作符:new
动态申请内存释放操作符:delete

1. 申请动态数组

1.1 一位数组

申请内存语法:

data_type* array_ptr = new data_type[exp]; 
//第一个data_type代表数组元素的数据类型
//*表示声明结果为一个指针
//array_ptr既是这个数组的名,也是数组首元素的地址
//exp可以是常量表达式,也可以是运行时才能确定的变量

释放内存语法:

delete[] array_ptr; 
//[]表示释放内存的是array_ptr指向的整个数组,而不仅仅是首元素的指针

来看以下示例:

Point::~Point() {
    count--;
    //在析构函数中增加一句输出打印
    cout << "A point has been delete\n";
};

void Point::move(int intx, int inty) {
    x = intx;
    y = inty;
};

int main(int argc, const char * argv[]) {
    Point::showCount();
    Point* points = new Point[2];
    //通过数组下标访问数组元素
    points[0].move(1, 2);
    points[1].move(4, 5);

    Point::showCount();
    //delete[] points;
    return 0;
}
运行结果1为:
Point number is : 0
Point number is : 2

运行结果2为:
Point number is : 0
Point number is : 2
A point has been delete
A point has been delete

首先我们将delete[] points注释掉,观察程序运行结果,可以看到,即使是主程序退出后,析构函数也没有被调用,显然,两个Point对象都还存在于内存中,但是指向他们的指针变量已经随着mian函数退出失效了,造成了内存泄漏。加上delete操作后,可以看到,对象内存被正确的释放了。

1.2 二维数组

申请内存语法:

data_type (*array_ptr)[exp_2]...[exp_n] = new data_type[exp_1][exp_2]...[exp_n]; 
//n维数组可以表示为由n-1维数组构成的数组
//array_ptr既是这个n维数组的名,也是指向第一个n-1维数组的指针
//[exp_2]...[exp_n]表示每一个n-1维数组的大小
//exp_i可以是常量表达式,也可以是运行时才能确定的变量

释放内存语法:

delete[] array_ptr; 
//[]表示释放内存的是array_ptr指向的整个数组,无论几维数组,只要写一个即可

2. 动态数组类

把存放同一类对象的元素封装在一个类中,就是动态数组类,使用动态数组类的好处是可以自动动态申请和释放内存空间,如下示例:

//定义动态数组类存放Point对象的数组
class ArrayOfPoint {
public:
    ArrayOfPoint();
    //构造函数
    ArrayOfPoint(int size) {
        this -> size = size;
        points = new Point[size];
    };

    ~ArrayOfPoint(){
        //在析构函数中释放资源
        cout << "deleting.." << endl;
        delete [] points;
    };
    Point& element(int index) {
        assert(index >= 0 && index < size);
        return points[index];
    };
private:
    //私有成员变量不包含数组,只有一个指针和数组元素大小
    Point *points;
    int size;
};
int main(int argc, const char * argv[]) {
    //定义point动态数组对象
    ArrayOfPoint points(3);
    points.element(0).move(1, 2);
    points.element(1).move(4, 5);
    points.element(0).showCount();
    return 0;
}
输出结果为:
Point number is : 3
deleting..
A point has been delete
A point has been delete
A point has been delete

可以看到,退出主程序之前,points对象被自动释放,也就是自动调用它的析构函数,从而释放了整个数组中三个point对象的内存资源。

3. 智能指针

unique_ptr:
不允许多个指针指向同一块内存空间,可以用标准库中move函数转移指针。
shared_ptr:
多个指针共享资源。
weak_ptr:
可复制shared_ptr,构造时或释放时不对资源产生影响。

4. 对象的深层复制与浅层复制

浅层复制:前面我们对类的复制构造函数有了简单的了解,并且知道c++在编译时会给没有自定义复制构造函数的类添加一个默认的复制构造函数,这个复制构造函数的功能就是按照成员变量一一对应赋值的形式来进行复制。这就是浅层复制。
如果类的成员变量包含指针时,这种复制方法就存在一定的问题,具体看示例:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值