动态数组
首先:为什么需要动态定义数组呢?
这是因为,很多情况下,在预编译过程阶段,数组的长度是不能预先知道的,必须在程序运行时动态的给出
但是问题是,c++要求定义数组时,必须明确给定数组的大小,要不然编译通不过
如: int Array[5];正确
int i=5;
int Array[i]; 错误 因为在编译阶段,编译器并不知道 i 的值是多少
那么,我们该如何解决定义长度未知的数组呢?
答案是:new 动态定义数组
因为new 就是用来动态开辟空间的,所以当然可以用来开辟一个数组空间
这样,下面的语句:
int size=50;
int *p=new int[size]; 是正确的
但是二维动态数组能不能也这样定义呢
int size=50,Column=50;
int (*p)[Column]=new int [size][Column]
这样的语句,编译器通不过,为什么呢?
首先 new int[size][Column] 就是动态生成时确定的,所以它没有错
那么就是 int(*p)[Column],这句有问题了,这句为什么不对呢, 那是因为,这是一个定义语句,而定义语句先经过编译器进行编译,当编译器运行到此处时,发现Column 不是常数,因此不能通过编译。 而之所以编译器认为Column 不是常数,是因为编译阶段,编译器起的作用是查语法错误,和预分配空间,它并不执行程序,因此,没有执行那个赋值语句(只是对这个语句检查错误,和分配空间),因此编译阶段,它将认为column 是个变量。所以上面的二维数组定义是错误的, 它不能通过编译。
改成这样:
int size=50
int (*p)[50]=new int [size][50]
便正确了。
由此可见,这种动态分配数组,仅对一维数组空间是真正动态分配的。
但是如何真正的动态分配二维数组呢,即如果Column 也不能预先知道的话,该如何处理呢?
上面的动态分配已经不能满足我们的要求,因为上面动态分配只对一维数组是真正动态的,对二维数组的话,必须编译之前预先知道二维数组每一列的长度,而这个长度在很多情况下是不能预先知道的,所以我们得结合其他方法来解决这个问题。
既然一维是真正的动态分配的话,那我们利用这一特性定义一个指针数组。
int **p= new int*[size];//定义指针数组
int *p[5];// 假若知道二维数组的行数为5
然后对指针数组中的每一个指针分配一个一维数组空间,这样便动态定义了二维数组
事实上,我认为指针数组的主要用途,就在于动态定义多维数组
for(int i=0;i<size;i++)
{
p[i]=new int[Column];
}
运行完毕后,一个二维数组便被动态的成功建立
-----------------------------------
例子:
size =6;
column =5
int **p=new int*[size];
for(int i=0;i<size;i++)
{
p[i]=new int[Column];
}
所生成的动态数组如下图所示:
最后 ,因为调用了new, 千万千万别忘记在用完之后,将其所占资源 delete 掉
下面是delete方法:
for(int i=0;i<size;i++)
{
delete [] p[i]; // 要在指针前加[] , 否则的话 只释放p[i]所指的第一个单元所占的空间
}
delete [] p; //最后不要忘掉 释放掉开辟的指针数组 :》
// ArrayTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "ArrayTest.h"
#include <afxstr.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 唯一的应用程序对象
CWinAPP theApp;
using namespace std;
// ArrayTest.cpp : 定义控制台应用程序的入口点。
//
CString** CreateCStringArray(UINT colcount, UINT rowcount){
CString** strMsg = new CString*[colcount];
for (UINT i = 0; i < colcount; i++)
{
strMsg[i] = new CString[rowcount];
}
return strMsg;
}
POINT** CreatePOINTArray(UINT colcount, UINT rowcount)
{
POINT** Point = new POINT*[colcount];
for (UINT i = 0; i < colcount; i++)
{
Point[i] = new POINT[rowcount];
}
return Point;
}
void DeleteCStringArray(UINT size, CString** pstr)
{
for (unsigned int i = 0; i < size; i++)
{
delete[] pstr[i]; // 要在指针前加[] , 否则的话 只释放p[i]所指的第一个单元所占的空间
}
}
void DeletePOintArray(UINT size, POINT** pPoint)
{
for (UINT i = 0; i < size; i++)
{
delete[] pPoint[i]; // 要在指针前加[] , 否则的话 只释放p[i]所指的第一个单元所占的空间
}
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
HMODULE hModule = ::GetModulehandle(NULL);
if (hModule != NULL)
{
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(hModule, NULL, ::GetcommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: MFC 初始化失败\n"));
nRetCode = 1;
}
else
{
// TODO: 在此处为应用程序的行为编写代码。
// 定义字符串数组--动态数组
CString** strMsg = CreateCStringArray(8, 16);
strMsg[0][0] = L"AddressWidth";
strMsg[0][1] = L"Architecture";
strMsg[0][2] = L"Availability";
strMsg[0][3] = L"Caption";
strMsg[0][4] = L"ConfigManagerERRORCode";
strMsg[0][5] = L"ConfigManagerUserConfig";
strMsg[0][6] = L"cpuStatus";
strMsg[0][7] = L"CreationClassName";
strMsg[0][8] = L"CurrentClockSpeed";
strMsg[2][0] = L"InstallDate";
strMsg[2][1] = L"L2cacheSize";
strMsg[2][2] = L"L2CacheSpeed";
strMsg[2][3] = L"L3CacheSize";
strMsg[2][4] = L"L3CacheSpeed";
strMsg[2][5] = L"LastErrorCod";
strMsg[2][6] = L"Level";
strMsg[2][7] = L"LoadPercentage";
strMsg[2][8] = L"Manufacturer";
strMsg[2][9] = L"MaxClockSpeed";
strMsg[2][10] = L"Name";
strMsg[2][11] = L"NumberOfCores";
strMsg[2][12] = L"NumberOfLogicalProcessors";
strMsg[2][13] = L"OtherFamilyDescription";
strMsg[2][14] = L"PNPdeviceid";
strMsg[2][15] = L"PowerManagementCapabilities";
strMsg[4][0] = L"ProcessorId";
strMsg[4][1] = L"ProcessorType";
strMsg[4][2] = L"Revision";
strMsg[4][3] = L"Role";
strMsg[4][4] = L"socketDesignation";
strMsg[4][5] = L"Status";
strMsg[4][6] = L"StatusInfo";
strMsg[4][7] = L"Stepping";
strMsg[4][8] = L"SystemCreationClassName";
strMsg[4][9] = L"SystemName";
strMsg[4][10] = L"uniqueId";
strMsg[4][11] = L"UpgradeMethod";
strMsg[4][12] = L"VoltageCaps";
////////////////////////////////////////////////////////////////////////////
strMsg[4][13] = L"ErrorCleared";
strMsg[4][14] = L"ErrorDescription";
strMsg[4][15] = L"ExtClock";
strMsg[6][0] = L"InstallDate";
strMsg[6][1] = L"L2CacheSize";
strMsg[6][2] = L"L2CacheSpeed";
strMsg[6][3] = L"L3CacheSize";
strMsg[6][4] = L"L3CacheSpeed";
strMsg[6][5] = L"LastErrorCod";
strMsg[6][6] = L"Level";
strMsg[6][7] = L"LoadPercentage";
strMsg[6][8] = L"Manufacturer";
strMsg[6][9] = L"MaxClockSpeed";
strMsg[6][10] = L"Name";
strMsg[6][11] = L"NumberOfCores";
strMsg[6][12] = L"NumberOfLogicalProcessors";
strMsg[6][13] = L"OtherFamilyDescription";
strMsg[6][14] = L"PNPDeviceID";
strMsg[6][15] = L"PowerManagementCapabilities";
for (UINT i = 0; i < 8; i++)
{
for (UINT j = 0; j < 16; j++)
{
printf("%ls\n", strMsg[i][j]);
}
printf("--------------i = %d\n", i);
}
DeleteCStringArray(8, strMsg);
//// 定义坐标数组
POINT** Point = CreatePOINTArray(8, 16);
POINT p1;
p1.x = 1.0;
p1.y = 2.0;
Point[0][0] = p1;
Point[0][1] = p1;
Point[0][2] = p1;
Point[0][3] = p1;
Point[0][4] = p1;
Point[0][5] = p1;
Point[0][6] = p1;
Point[0][7] = p1;
Point[0][8] = p1;
Point[1][0] = p1;
Point[1][1] = p1;
Point[1][2] = p1;
Point[1][3] = p1;
Point[1][4] = p1;
Point[1][5] = p1;
Point[1][6] = p1;
Point[1][7] = p1;
Point[1][8] = p1;
for (UINT i = 0; i < 8; i++)
{
for (UINT j = 0; j < 16; j++)
{
printf("%d\n", Point[i][j]);
}
printf("--------------i = %d\n", i);
}
DeletePOintArray(8, Point);
}
}
else
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: GetModuleHandle 失败\n"));
nRetCode = 1;
}
return nRetCode;
}
二, C、C++之动态数组的实现
相关阅读
题目地址:https://vjudge.net/problem/HihoCoder-1121 题目: 描述 大家好,我是小Hi和小Ho的小伙伴Nettle,从这个星期开始由我来完成我
offsetofRetrieves the offset of a member from the beginning of its parent structure.返回结构成员相对于结构开头的字节偏移
一、简介 由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete。程序员忘记 delete,流程太复杂,最终导致
今天看书看到侯捷的《STL源码剖析》里提到trivial和non-trivial及POD类型,查了些资料理解了一下。trivial意思是无意义,这个triv
(1)函数指针与指针函数 (1)函数指针 一种特殊的指针,它指向函数的入口; /* * 定义一个函数指针p,只能指向返回值为int,形参为两个int的函