• C++指针和动态内存分配


    指针和动态内存分配

    数组与指针

    数组

    • 数组名是一个指针常量。
    • 数组名传递数据时,传递的是地址。
    • 数组作为函数参数时不指定第一维大小。
    • 对象数组

    A a[2] = {A(1,2)};

    执行时先调用有参数的构造函数初始化a[0],然后调用默认构造函数初始化a[1]。

    指针

    1. 指向常量的指针 。不能改变所指对象的值,但可以指向其他对象。
        int a;
        const int* p1 = &a;
        int b;
        p1 = &b;//正确,可以指向其他对象。
        *p1 = 1;//错误,不能改变所指对象的值
    
    1. 指针类型的常量 。指针本身的值不能被改变。
        int a,b;
        int* const p1 = &a;
        p1 = &b; //错误,指针本身的值不能被改变
    

    指针数组

        int line1[] = {1,0,0};
        int line2[] = {0,1,0};
        int line3[] = {0,0,1};
        int* PLine[] = {line1,line2,line3};
        for(int i = 0;i < 3;++i){
            for(int j = 0;j < 3;++j)
                cout<<PLine[i][j]<<" ";
            cout<<endl;
        }
    

    !

    函数指针

    void foo(int a){
        cout<<"cout foo"<<a<<endl;
    }
    void bar(int b){
        cout<<"cout bar"<<b<<endl;
    }
    int main()
    {
        void (*ptr)(int);
        ptr = foo;
        ptr(1);
        ptr = bar;
        ptr(2);
        return 0;
    }
    

    对象指针

    指向对象的指针

    Point* ptr;
    Point p1;
    ptr = &p1;//指向一个对象
    p->getX(); //(*p).getX() 调用相应的成员
    
    this指针

    this指针是隐含于每一个类的非静态成员函数中的特殊指针,用于指向正在被成员函数操作的对象。

    动态内存分配

    一般对象的动态内存分配

    在C++中建立和删除堆对象使用的两个操作符:new和delete。

    *new操作 *

    该语句运行过程中申请分配用于存放指定类型数据的内存空间,并根据初始化参数列表中的值进行初始化。如果内存申请成功,便 返回一个指向新分配内存首地址的类型的指针 。可以通过该指针对堆对象进行访问。如果申请失败则抛出异常。

    • 分配基本类型的变量。
        int* p = new int; //分配内存后不设初值。
        int* p1 = new int();//分配内存后,用0来初始化。
        int* p1 = new int(1);
    
    • 分配类类型变量
        class Point {
        public:
            Point():x(0),y(0){  
                cout<<"Default constructor called."<<endl;
            }
            Point(int x,int y):x(x),y(y){
                cout<<"Constructor called."<<endl;
            }
            ~Point(){cout<<"Destructor called."<<endl;}
        private:
            int x,y;
        };
        int main()
        {
            cout<<"Step one"<<endl;
            Point* ptr1 = new Point;//未给出参数列表,调用默认ctor
            delete ptr1;//删除对象,调用dtor
     
            cout<<"Step two"<<endl;
            ptr1 = new Point(1,2);//给出参数列表,调用有形ctor
            delete ptr1;//删除对象,调用dtor
            return 0;
        }
    

    注意:

    1. 用new建立一个类类型的变量时,如果该类存在用户定义的默认ctor,则“new T”和“new T()”的效果是相同的。
    2. 若用户没有定义默认的ctor,使用“new T”创建对象时,会调用系统隐含的ctor;使用“new T()”创建对象时,系统除了执行那些操作外,还会为基本数据类型和指针类型赋0,而且过程是递归的。

    delete操作
    如果被删除的是对象,对象的析构函数将被调用。用new建立的对象,只能用delete删除一次。

    动态数组

    一维数组

    int* arr = new int[n]; //new T
    int* arr = new int [n]() ;//new T()
    int* arr = new int [n](1) ;//用1初始化。
    delete[] arr;//删除整个数组。
    

    多维数组的分配

    /*
        new 类型名T[第一维][第二维]…
        分配一个2*3*4的三位数组的两种方法。
        1.整个分配,释放的时候是整个释放掉。
        2.一层一层分配,释放的时候也是从内而外一层一层释放。
        */
        int(*cp)[3][4];
        cp = new int [2][3][4]();
        delete cp;
     
        //分配空间
        int*** p = new int**[2];
        for(int i = 0;i < 2; ++i){
            p[i] = new int*[3];
            for(int j = 0;j < 3; ++j)
                p[i][j] = new int[4]();
        }
        //赋值
        for(int i = 0;i < 2; ++i)
            for(int j = 0;j < 3; ++j)
                for(int k = 0;k < 4; ++k)
                    p[i][j][k] = i*j*k;
        //释放空间
        for(int i = 0;i < 2; ++i){
            for(int j = 0;j < 3; ++j)
                delete[] p[i][j];
            delete[] p[i];
        }
        delete[] p;
    

    深拷贝和浅拷贝

    隐含的拷贝构造函数完成的是浅拷贝。
    浅拷贝与深拷贝的区别如图。

    class Point{
        ...
    };
    class ArrayOfPoint{
    public:
        ArrayOfPoint(const ArrayOfPoint& v);
    private:
        Point* points;
        int size;
    };
    ArrayOfPoint::ArrayOfPoint(const ArrayOfPoint& v)
    {
        //深拷贝,为新的对象重新开辟一片内存空间。
        size = v.size;
        points = new Point[size];
        for(int i = 0;i < size; ++i)
            points[i] = v.points[i];
    }
    
  • 相关阅读:
    [记录] web icon 字体
    ruby sass Encoding::CompatibilityError for changes
    [CSS][转载]内层div的margin-top影响外层div
    PHP 有关上传图片时返回HTTP 500错误
    APK downloader
    阿里云CentOS7.2卸载CDH5.12
    CentOS7查询最近修改的文件
    service cloudera-scm-server restart报错 Unable to retrieve remote parcel repository manifest
    CDH安装报错 Monitor-HostMonitor throttling_logger ERROR ntpq: ntpq -np: not synchronized to any server
    CDH5.12安装检查Inspector failed on the following hosts...
  • 原文地址:https://www.cnblogs.com/Sinte-Beuve/p/4805569.html
Copyright © 2020-2023  润新知