zoukankan      html  css  js  c++  java
  • [C++对象模型][3]指针与数组

    数组可以看做为一种类型,与指针不同,但是可以相互转化。

    一 C指针操作函数

    new和delete对C++的程序员也许很熟悉,但是malloc和free被用来在C代码中用来内存分配和释放,很多C++开发者并不能游刃有余的使用,下面实例解析malloc和free的使用。

           malloc void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针。如果分配失败,则返回一个空指针(NULL)。
           free void free(void *FirstByte): 该函数是将之前用malloc分配的空间还给程序或者是操作系统,也就是释放了这块内存,让它重新得到自由。

    实例如下:

    Code
    #pragma once
    #include 
    <string>

    void TestMallocAndFree()
    {
        
    char *ptr = NULL;
        ptr 
    = (char*)malloc(100 * sizeof(char));
        
    if (NULL == ptr)
        {
            
    return;
        }
        memcpy(ptr,
    "Hello!",strlen("Hello!"));
        free(ptr);
        ptr 
    = NULL;

         typedef 
    struct data_type 
         {
           
    int age;
           
    char *name;
         } data;
     
         data 
    *willy = NULL;
         willy 
    = (data*) malloc( sizeof(data) );
         willy
    ->age = 20;
         willy
    ->name = "jason"// 此时的name指向了常量区,所以name指针不需要程序员释放。
         free( willy );
         willy 
    = NULL;
    }

    malloc/free 和new/delete的区别:

    1)new/delete是保留字,不需要头文件支持. malloc/free需要头文件库函数支持. 使用malloc/free需要包含 #include<cstdlib> 或<stdlib>.

    2) new 建立的是一个对象,new会根据对象计算大小,直接返回对象的指针,当使用完毕后调用delete来释放,但malloc分配的是一块内存,需要用户制定所要分配内存的大小,而且返回的均为void的指针,使用时需要相应的强制类型转化,使用结束后调用free来释放内存.

    3)new/delete的使用除了分配内存和释放,还调用了类型的构造函数和析构函数,而malloc/free只是简单的分配和释放内存。

    二 数组与指针

    C++的数组经常需要和指针来结合使用,下面来进行相关的强化训练。实例如下:

    Code
    #pragma once
    #include 
    <iostream>
    using namespace std;

    void PrintArray(double *p, int num)
    {
        
    for(int i = 0; i < num; ++i)
        {
            cout 
    << " " << p[i] << " ";
        }
        cout 
    << endl << "The array is end!" << endl;
    }
    void PrintArray(double arr[3]) 
    {
        
    for(int i = 0; i < 3++i)
        {
            cout 
    << " " << *(arr+i)/*arr[i]*/ << " ";
        }
        cout 
    << endl << "The array is end!" << endl;
    }
    void ChangeArray(double arr[3]) // 数组传参为传指针,所以函数内可以修改
    {
        
    for(int i = 0; i < 3++i)
        {
            arr[i] 
    = 10;
        }
    }
    void PrintArray(double arr[3][3])
    {
        
    for(int i = 0; i < 3++i)
            
    for(int j = 0; j < 3++j)
                cout 
    << " " << arr[i][j] << " ";
        cout 
    << endl << "The array is end!" << endl;
    }

    int GetLength(){return 3;}

    void TestArray()
    {
        
    // 数组的定义和初始化
        short months[12= {31,28,31,30,31,30,31,31,30,31,30,31};
        
    double arr[3]; 
        arr[
    0= 1.0;
        arr[
    1= 2.0;
        arr[
    2= 3.0;
        
    double arr2[] = {1.0,2.0,3.0};
        
    //double arr3[3] = arr; // error
        PrintArray(arr,3);
        PrintArray(
    &arr[0],3);
        PrintArray(arr2);

        
    double matrix2 [2][2= {1.0,0.0,0.0,1.0};
        
    double matrix3 [3][3= {{1.0,0.0,0.0},
                                {
    0.0,1.0,0.0},
                                {
    0.0,0.0,1.0}};
        PrintArray(matrix3[
    0],3*3);
        PrintArray(
    &matrix3[0][0],3*3);
        
    //PrintArray(matrix3,3*3);
        PrintArray(matrix3);

        
    // 指针来模拟数组
        double *p3 = new double[GetLength()];
        p3[
    0= 10.0;
        p3[
    1= 20.0;
        p3[
    2= 30.0;
        PrintArray(p3,
    3);
        PrintArray(p3);
        delete []p3;

        
    // 数组+指针实现二维变长数组
        double *p4[2];
        p4[
    0= new double[2];
        p4[
    1= new double[4];
        p4[
    0][0= 10;
        p4[
    0][1= 20;
        p4[
    1][0= 30;
        p4[
    1][1= 40;
        p4[
    1][2= 50;
        p4[
    1][3= 60;
        PrintArray(p4[
    0],2);
        PrintArray(p4[
    1],4);
        delete [] p4[
    0];
        delete [] p4[
    1];

        PrintArray(arr); 
    // 数组传参为传指针,所以函数内可以修改
        ChangeArray(arr);
        PrintArray(arr);
    }

    代码分析总结:

    1)数组的定义必须使用常量指定长度,例如:double arr[3],但是使用指针时可以是运行时指定,例如double *p3 = new double[getLength()]。
    2)数组定义时即分配空间且在栈上,不需要程序员来对内存管理,但是如果对指针使用了new[],则必须由程序员在使用完毕后delete[]。
    3) 一维数组数组名即第一个元素的地址,例如:double arr[3]中,arr == &arr[0]为true。
    4)二维数组中第一行的地址即为第一个元素的地址,例如:double matrix3 [3][3],matrix[0] == &matrix[0][0]为true。
    5)可以使用指针数组来模拟变长二维数组,例如:double *p4[2]; p4[0] = new double[2]; p4[1] = new double[4];
    6)二维数组内存中同一维数组仍为连续的区域,所以可以将二维数组和一维相互转化。
    7)一维数组名即为第一个元素的地址,所以可以同指针隐式转化,但二维数组名不是第一个元素地址,所以不能转化。
    8) 当函数传入数组,实际传首元素的指针,所以可以在函数内修改数组元素。

    三 完!


    作者:iTech
    微信公众号: cicdops
    出处:http://itech.cnblogs.com/
    github:https://github.com/cicdops/cicdops

  • 相关阅读:
    如何用微软StreamInsight 处理和分析实时数据
    网站压力测试软件WebBench以及压测Jexus
    Xamarin 开源应用汇集
    微软开源 C++ REST SDK
    Visual Studio 2010/2012 Pro Power Tools
    深入浅出事件流处理NEsper(一)
    将Windows日志转换为Syslog
    事件流处理框架NEsper for .NET
    WCF技术剖析之二十一: WCF基本的异常处理模式[上篇]
    WCF技术剖析之二十一:WCF基本异常处理模式[下篇]
  • 原文地址:https://www.cnblogs.com/itech/p/1395434.html
Copyright © 2011-2022 走看看