c++基础(九)

第三部分:动态存储分配

用指针访问数组元素

数组是一组连续存储的同类型数据,可以通过指针的算术运算,使指针依次指向数组的各个元素,进而可以遍历数组。使用指针来访问数组元素时,需要将数组的首地址赋值给指针变量,形式为: int *p,a[10];p=a(或者p=&a[0])。

经过上述定义及赋值后*pa就是a[0],*(pa+1)就是a[1],... ,*(pa+i)就是a[i]。a[i], *(pa+i), *(a+i), pa[i]都是等效的。

指针数组

顾名思义,数组元素是指针的数组就叫做指针数组。我们可以用二维数组来存放矩阵,也可以用一维指针数组来存放矩阵,见下面案例。

以指针作为函数参数

为什么需要用指针做参数?

  • 需要数据双向传递时(引用也可以达到此效果)
  • 用指针作为函数的参数,可以使被调函数通过形参指针存取主调函数中实参指针指向的数据,实现数据的双向传递
  • 需要传递一组数据,只传首地址运行效率比较高
  • 实参是数组名时形参可以是指针,数组名作为函数参数时会退化为一个指针

动态分配与释放内存

语法格式:new 类型名T  (初始化列表)。其功能为:在程序执行期间,申请用于存放T类型对象的内存空间,并依初值列表赋以初值。结果为:成功:T类型的指针,指向新分配的内存;失败:抛出异常。释放内存:语法格式为 delete 指针p,功能为:释放指针P所指向的内存。

案例:

#include <iostream>
using namespace std;
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; }
    int getX() const { return x; }
    int getY() const { return y; }
    void move(int newX, int newY) 
    {
        x = newX;
        y = newY;
    }
private:
    int x, y;
};

int main() 
{
    cout << "Step one: " << endl;
    Point *ptr1 = new Point; //调用默认构造函数
    cout << "ptr1: ";
    cout << ptr1->getX() << "," << ptr1->getY() << endl;
delete ptr1; //删除对象,自动调用析构函数,释放动态分配的内存空间,不是删除ptr1
    cout << "Step two: " << endl;
    ptr1 = new Point(1, 2);//ptr1存放了新申请的内存空间地址
    cout << "ptr1: ";
    cout << ptr1->getX() << "," << ptr1->getY() << endl;
    delete ptr1;
    //getchar();
    return 0;
}

申请和释放动态数组:分配语法:new 类型T  [数组长度];释放语法:delete[] 数组名p。数组长度可以是任何整数类型的表达式,在运行时计算;释放内存时,不要忘记delete后的方括号[],如果没有这对方括号,那么在释放空间时只会释放动态数组的首地址对应的内存空间。

案例:

#include <iostream>
using namespace std;
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; }
    int getX() const { return x; }
    int getY() const { return y; }
    void move(int newX, int newY) 
    {
        x = newX;
        y = newY;
    }
private:
    int x, y;
};

int main() 
{
    Point *ptr = new Point[2]; //创建对象数组
    ptr[0].move(5, 10); //通过指针访问数组元素的成员
    ptr[1].move(15, 20); //通过指针访问数组元素的成员
    cout << "ptr[0]: ";
    cout << ptr->getX() << "," << ptr->getY() << endl;
    cout << "ptr[1]: ";
    cout << (ptr + 1)->getX()<<"," << (ptr+1)->getY() << endl;//通过指针访问对象成员名
    cout << "Deleting..." << endl;
    delete[] ptr; //删除整个对象数组
    return 0;
}

动态申请多维数组:new 类型名T[第一维长度][第二维长度]…

案例:

#include<iostream>
using namespace std;
int main()
{
    int(*cp)[9][8] = new int[7][9][8];
    for (int i = 0; i < 7; i++)
    {
        for (int j = 0; j < 9; j++)
        {
            for (int k = 0; k < 8; k++)
            {
                //*(*(*(cp + i) + j) + k) = i * 100 + j * 10 + k;
                cp[i][j][k] = i * 100 + j * 10 + k;
            }
        }
    }
    for (int i = 0; i < 7; i++)
    {
        for (int j = 0; j < 9; j++)
        {
            for (int k = 0; k < 8; k++)
            {
                cout << cp[i][j][k] << '\t';
            }
            cout << endl;
        }
        cout << endl;
    }
    delete[]cp;
    system("pause");
    return 0;
}

将动态数组封装成类:更加简洁,便于管理;可以在访问数组元素前检查下标是否越界。

案例:

#include <iostream>
#include<cassert>
using namespace std;
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; }
    int getX() const { return x; }
    int getY() const { return y; }
    void move(int newX, int newY)
    {
        x = newX;
        y = newY;
    }
private:
    int x, y;
};
class ArrayofPoints//定义一个动态数组类
{
public:
    ArrayofPoints(int size) :size(size)//初始化
    {
        points = new  Point[size];//动态分配存储空间
    }
    ~ArrayofPoints()//析构函数
    {
        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 count;
    cout << "Please enter the count of points:";
    cin >> count;
    ArrayofPoints points(count);
    for (int i = 0; i < count; i++)
    {
        points.element(i).move(i, i+5);
    }
    for (int i = 0; i < count; i++)
    {
        cout << "points[" << i << "]:" << "(" << points.element(i).getX() << ",";
        cout<< points.element(i).getY()<<")" << endl;
    }
    return 0;
}

运行结果:

智能指针:

  • 显式管理内存在性能上有优势,但容易出错。
  • C++11提供智能指针的数据类型,对垃圾回收技术提供了一些支持,实现一定程度的内存管理
  • unique_ptr :不允许多个指针共享资源,可以用标准库中的move函数转移指针
  • shared_ptr :多个指针共享资源
  • weak_ptr :可复制shared_ptr,但其构造或者释放对资源不产生影响

猜你喜欢

转载自www.cnblogs.com/puheng/p/9345943.html
今日推荐