آرایه‌های دو بعدی کاربردهای بسیاری از جمله جداول و ماتریس‌ها دارند. اهمیت تعریف آرایه‌های پویای دو بعدی کمتر از آرایه‌های یک بعدی نیست. آرایه‌های پویای دو بعدی یک ویژگی جالب در مقایسه با آرایه ایستا دارند: شما با تعریف پویای آرایه‌های دو بعدی می‌توانید جداول غیرمستطیلی تشکیل بدهید. در واقع وقتی شما آرایه‌های دو بعدی را به صورت پویا ایجاد می‌کنید، این اختیار را دارید که تعداد ستون‌های هر ردیف را متفاوت انتخاب کنید.
به قطعه کد زیر توجه کنید:
کد:
 int **table;
 cin >> n;
 table = new int*[ n ];
 register int i, j;
 for ( i = 1 ; i <= n ; i++ )
 {
   table[ i - 1 ] = new int[ i ];
   for ( j = 1 ; j <= i ; j++ )
   {
     table[ i - 1 ][ j - 1 ] = i * j;
   }
 }
 .
 .
 .
 for ( i = 0 ; i < n ; i ++ )
 {

   delete[] table[ i ];
 }
 delete[] table;
این کد عدد n را از کاربر گرفته و نیمه پایینی جدول ضرب n در n را در یک آرایه پویا ذخیره می‌کند. جدول ضرب اعداد متقارن است و نیازی به ذحیره کردن اعداد همه خانه‌های جدول نیست. در نتیجه با آرایه پویای دو بعدی حافظه مصرفی تقریبا نصف می‌شود.
متغیر table که به صورت table** تعریف شده است، یک اشاره‌گر به اشاره‌گر است. کامپایلر وقتی با دستور

کد:
table = new int*[ n ];
مواجه می‌شود، یک آرایه پویای یک بعدی به طول n از اشاره‌گرهای صحیح ایجاد می‌کند. پس عناصر

کد:
table[ 0 ], table[ 1 ], ..., table[ n - 1 ]
هر کدام یک اشاره‌گر از نوع صحیح هستند. حال با دستور


کد:
table[ i - 1 ] = new int[ i ]
برای هر اشاره‌گر یک آرایه پویای یک بعدی منسوب می‌کنیم.
مثلا به ازای n = 3 عناصر table به صورت زیر هستند:

کد:
table[ 0 ][ 0 ] 

 table[ 1 ][ 0 ], table[ 1 ][ 1 ]
 table[ 2 ][ 0 ], table[ 2 ][ 1 ], table[ 2 ][ 2 ]
با استفاده از چنین ساختاری به سادگی می‌توانید ماتریس‌ها و سایر داده‌ها با فرم چدول دو بعدی را پیاده‌سازی کنید. بزرگترین مزیت این حالت به حالت آرایه استاتیک استفاده صحیح از حافظه در دسترس است.