我爱电脑技术论坛's Archiver

bbs23 发表于 2008-4-23 07:14

怎样在C++中动态分配二维数组

这个问题应该是我以前在CSDN蹭分时回答次数比较多的一个问题了,我的回答一般是三种方法:(1)用vector的vector,(2)先分配一个指针 数组,然后让里面每一个指针再指向一个数组,这个做法的好处是访问数组元素时比较直观,可以用a[x][y]这样的写法,缺点是它相当于C#中的一个锯齿 数组,内存空间不连续。(3)直接分配一个x*y大小的一维数组,这样保证空间是连续的,但访问数组元素不直观。对于我这个“经典”回答,我那时还一直是 挺得意的,至少从蹭分的角度来看,这样回答还是很有效的。 vawQEa]z
  今天在ChinaUnix论坛闲逛时看到一个贴子,再次证明了我在C++方面才疏学浅。
R7`!\*AS a+NXO6I pX
I7kn7EZb b(U   #include <stdio.h>
&h.i\;E*a!k   #include <stdlib.h>/t3q1A?.SM _'I r
  #include <string.h>
$C`B3p)C/In^*~   void **darray_new(int row, int col, int size) w5~8F*Z%t)In$kV
  {        },`6j G!m*]r R
   void **arr;      
R|Q%cYp ^eP k}    arr = (void **) malloc(sizeof(void *) * row + size * row * col);        if (arr != NULL)       6Y:?Rn0Xt$y,YFI
  {               
y/IoL"z^        void *head;               
o"wd-xa}a        head = (void *) arr + sizeof(void *) * row;                       memset(arr, 0, sizeof(void *) * row + size * row * col);              while (row--)                        ?BG[d
            arr[row] = head + size * row * col;         }QDI J
     }        
c]N#n!Y8O        return arr;-yIKDE:l
  }
Zx7[i~x @%j   void darray_free(void **arr)
*M,Ap+ju%PZm   {        K*\_~3\;]%s/v
     if (arr != NULL)               
h2k~S0qzZ     free(arr);
6Lw2p6L5F,PK4m/r*Y   }:IA-w~iX3Q.HI.x

r#P8mPct*s(p)? a   嗯,连续分配内存,而且可以用a[x][y]的方式来访问!可谓二维数组动态分配的绝妙方法!这段程序是C的,似乎要改成支持对象分配的C++版也不是什么难事(不过估计得用上placement new吧,嗯,需要再思考一下……)。
Y C&SOH0L/a
8o&E6r2h+U-E,DV   2007-06-13 12:38 补充:l6Xr Z:`

"L.YH T|;_o0S-r,M"D   经过试验,C++版出炉了:)关键点还是在于placement new和显示的析构函数调用,用于保证对象可以正常的构造和析构。
9m*Q6xi*sK   这个实现也还是有不少缺点的,比如,数组的大小必须记住,才能保证析构所有对象。不过这点可以通过改进分配方法算法,把数组大小也用一点空间保存起来。
Z0}~/z G   另一个缺点是,从语法上看,很容易让人误把darray_new返回的指针以为是数据区的起始地址,从而可能导致一些逻辑错误。 y M ?!eM0t;N Ufq

3oQHv I2z   #include <iostream>!X Z*e;uB7` ju
  #include <cstdlib>FUpC%Qh
  #include <new>
E`-G+N/f,E t(B F3G;cqR(W6W7M
  template <typename T>
A/p,N/r;X%yN7ht:m   T **darray_new(int row, int col)
k3K9wSs)@'p/NAr   {`P4}4Btay8w9a
     int size = sizeof(T);doCL \&|6[
      void **arr = (void **) malloc(sizeof(void *) * row + size * row * col);v&m%Q Nd"gO6Z6A
      if (arr != NULL)J v8C Ve ]x
      {6M7R+t1L^
          unsigned char * head;
Z B'}.LRQ BH i           head = (unsigned char *) arr + sizeof(void *) * row;
~0{!T,j\O           for (int i = 0; i < row; ++i)| gM/H J
          {
"KR4gm8{/w u               arr[i] =  head + size * i * col;
9d[k'EJHs1]               for (int j = 0; j < col; ++j)
)kQ+]yf{                   new (head + size * (i * col + j)) T;EK%iJ)sC0c!Z
          }
z X[-mEl3yg*?       }
!p Z(gf)[P\       return (T**) arr;4[;mcN7A,Ift(^
  }$UK/f0A5xHy
#U y-{-h2p$r$[nB H
  template <typename T>
(WrOdrN V8U)^YA1r   void darray_free(T **arr, int row, int col)
X/T}GQ.Mc1y   {
\)['t r:s%e)D&]       for (int i = 0; i < row; ++i)
T'qc0zg%Z3w5fX t           for (int j = 0; j < col; ++j) x3C%o&j3R!@m
              arr[i][j].~T();jr4w9l$v nx
      if (arr != NULL)8D+_8PJ%dRA^
          free((void **)arr);
gxKf|   }

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.