动态创建二维vector数组 C和C++ 及指针与引用的区别
二维vector
vector<vector <int> > ivec(m ,vector<int>(n)); //m*n的二维vector
动态创建m*n的二维vector
方法一:
vector<vector <int> > ivec;
ivec.resize(m);
for(int i=0;i<m;i++) ivec[i].resize(n);
方法二:
vector<vector <int> > ivec;
ivec.resize(m,vector<int>(n));
动态创建二维数组a[m][n]
C语言版:
#include<malloc.h>
int **a=(int **)malloc(m*sizeof(int *));
for(int i=0;i<m;i++)
a[i]=(int *)malloc(n*sizeof(int));
C++版:
int **a=new int*[m];
for(int i=0;i<m;i++) a[i]=new int[n];
初始化二维数组
vector<vector <int> > ivec(m ,vector<int>(n,0)); //m*n的二维vector,所有元素为0
C++中用new动态创建二维数组的格式一般是这样:
TYPE (*p)[N] = new TYPE [][N];
其中,TYPE是某种类型,N是二维数组的列数。采用这种格式,列数必须指出,而行数无需指定。在这里,p的类型是TYPE*[N],即是指向一个有N列元素数组的指针。
还有一种方法,可以不指定数组的列数:
int **p;
p = new int*[]; //注意,int*[10]表示一个有10个元素的指针数组
for (int i = ; i != ; ++i)
{
p[i] = new int[];
}
这里是将p作为一个指向指针的指针,它指向一个包含10个元素的指针数组,并且每个元素指向一个有5个元素的数组,这样就构建了一个10行5列的数组。 当数组使用完毕,释放空间的代码是:
for(int i = ; i != ; i++)
{
delete[] p[i];
}
delete[] p;
处理二维数组,可以用降维或是二维法。
降维法是用一位数组来接受二维数组,将二维元素的首地址&a[][]作为参数,传递给函数,函数用int *接受。
二维法就直接用二维数组来接受,但是需要指定列数。 如要想创建一个[m][n]的二维数组。
下面为通过动态创建一个指针数组的方法来动态创建二维数组的方法。
C版本:
double **data;
data = (double **)malloc(m*sizeof(double *));
for(int j=;j<m;j++)
{
data[j] = (double*)malloc(n*sizeof(double)); //这个指针数组的每个指针元素又指向一个数组。
} for (int i=;i<m;i++)
{
for (int j=;j<n;j++)
{
data[i][j]=i*n+j;//初始化数组元素
}
}
for (i=;i<m;i++)
{
free(data[i]); //先撤销指针元素所指向的数组
}
free(data); C++版本:
double **data;
data = new double*[m]; //设置行 或直接double **data=new double*[m]; 一个指针指向一个指针数组。
for(int j=;j<m;j++)
{
data[j] = new double[n]; //这个指针数组的每个指针元素又指向一个数组。
}
for (int i=;i<m;i++)
{
for (int j=;j<n;j++)
{
data[i][j]=i*n+j;//初始化数组元素
}
}
for (i=;i<m;i++)
{
delete[] data[i]; //先撤销指针元素所指向的数组
}
delete[] data; 这种方法是通过先动态创建一个指针数组,然后为指针数组的每个元素再动态指向一个数组的办法来完成的。其创建过程与销毁过程两样重要。
在销毁的过程,先销毁指针数组每个元素指向的数组,然后再销毁这个指针数组。
.使用数组指针,分配一个指针数组,将其首地址保存在b中,然后再为指针数组的每个元素分配一个数组
int **b=new int*[row]; //分配一个指针数组,将其首地址保存在b中
for(i=;i<row;i++) //为指针数组的每个元素分配一个数组
b[i]=new int[col];
该方法定义的动态二维数组的释放需先释放指针数组的每个元素指向的数组,然后再释放该指针数组:
for(i=;i<row;i++)
{
delete [col]b[i];
b[i]=NULL;
}
delete [row]b;
b=NULL;
int _tmain(int argc, _TCHAR* argv[])
{
int row,column;
cin>>row>>column;
//方法一
//申请空间
int ** a = new int *[row];
for(int i = ;i < row;i++)
a[i] = new int[column];
//使用空间
for(int j = ;j < row;j++)
for(int k = ;k< column;k++)
a[j][k] = rand()%;
for(int j = ;j < row;j++)
{
cout<<endl;
for(int k = ;k< column;k++)
{
a[j][k] = rand()%;
cout<<a[j][k]<<" ";
}
}
//释放空间
for(int i = ;i < row;i++)
{
delete a[i];
a[i] = NULL;
}
delete [row]a;
a = NULL;
return ;
}
用vector
int _tmain(int argc, _TCHAR* argv[])
{
int row,column;
cin>>row>>column;
//方法二
//申请空间
vector<vector<int> > a(row,vector<int>(column));
//使用空间
for(int j = ;j < row;j++)
for(int k = ;k< column;k++)
a[j][k] = rand()%;
for(int j = ;j < row;j++)
{
cout<<endl;
for(int k = ;k< column;k++)
{
a[j][k] = rand()%;
cout<<a[j][k]<<" ";
}
}
return ;
}
首先,要认识到在任何情况下都不能用指向空值的引用。一个引用必须总是指向某些对象。因此如果你使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时你应该把变量声明为指针,因为这样你可以赋空值给该变量。相反,如果变量肯定指向一个对象,例如你的设计不允许变量为空,这时你就可以把变量声明为引用。
| char *pc = 0; // 设置指针为空值 char& rc = *pc; // 让引用指向空值 |
这是非常有害的,毫无疑问。结果将是不确定的(编译器能产生一些输出,导致任何事情都有可能发生),应该躲开写出这样代码的人除非他们同意改正错误。如果你担心这样的代码会出现在你的软件里,那么你最好完全避免使用引用,要不然就去让更优秀的程序员去做。我们以后将忽略一个引用指向空值的可能性。
因为引用肯定会指向一个对象,在C里,引用应被初始化。
| string& rs; // 错误,引用必须被初始化 string s("xyzzy"); string& rs = s; // 正确,rs指向s |
指针没有这样的限制。
| string *ps; // 未初始化的指针 // 合法但危险 |
不存在指向空值的引用这个事实意味着使用引用的代码效率比使用指针的要高。因为在使用引用之前不需要测试它的合法性。
| void printDouble(const double& rd) { cout << rd; // 不需要测试rd,它 } // 肯定指向一个double值 |
相反,指针则应该总是被测试,防止其为空:
| void printDouble(const double *pd) { if (pd) { // 检查是否为NULL cout << *pd; } } |
指针与引用的另一个重要的不同是指针可以被重新赋值以指向另一个不同的对象。但是引用则总是指向在初始化时被指定的对象,以后不能改变。
| string s1("Nancy"); string s2("Clancy"); string& rs = s1; // rs 引用 s1 string *ps = &s1; // ps 指向 s1 rs = s2; // rs 仍旧引用s1, // 但是 s1的值现在是 // "Clancy" ps = &s2; // ps 现在指向 s2; // s1 没有改变 |
总的来说,在以下情况下你应该使用指针,一是你考虑到存在不指向任何对象的可能(在这种情况下,你能够设置指针为空),二是你需要能够在不同的时刻指向不同的对象(在这种情况下,你能改变指针的指向)。如果总是指向一个对象并且一旦指向一个对象后就不会改变指向,那么你应该使用引用。
还有一种情况,就是当你重载某个操作符时,你应该使用引用。最普通的例子是操作符[]。这个操作符典型的用法是返回一个目标对象,其能被赋值。
| vector v(10); // 建立整形向量(vector),大小为10; // 向量是一个在标准C库中的一个模板 v[5] = 10; // 这个被赋值的目标对象就是操作符[]返回的值 |
如果操作符[]返回一个指针,那么后一个语句就得这样写:
| *v[5] = 10; |
但是这样会使得v看上去象是一个向量指针。因此你会选择让操作符返回一个引用。
当你知道你必须指向一个对象并且不想改变其指向时,或者在重载操作符并为防止不必要的语义误解时,你不应该使用指针。而在除此之外的其他情况下,则应使用指针。
动态创建二维vector数组 C和C++ 及指针与引用的区别的更多相关文章
- C语言 动态创建二维数组
/*C语言 如何动态创建二维数组 转化为一维数组申请数组,创建和释放都比较简单 */ #include <stdlib.h> #include <stdio.h> #inclu ...
- 【转】C++动态创建二维数组,二维数组指针
原作者博客:蒋国宝的IT技术博客 今天完成一道题目需要自己用指针创建一个二维的数组,不得不承认指针的确是恶心. int **result; ; ; result = new int*[row]; ; ...
- nodejs 动态创建二维码
<!--弹出二维码--> <div class="qrcode"> <div> <p id="saoma">扫描 ...
- C语言动态生成二维数组
# 动态创建二维数组示例 #include "stdlib.h" #include "stdio.h" #include <malloc.h> in ...
- 如何在C++中动态建立二维数组(转)
http://blog.sina.com.cn/s/blog_7c073a8d0100qp1w.html http://blog.163.com/wujiaxing009@126/blog/stati ...
- 转:用STL中的vector动态开辟二维数组
用STL中的vector动态开辟二维数组 源代码:#include <iostream>#include <vector>using namespace std;int mai ...
- c++中创建二维数组的几种方法
一.用new申请内存空间 int **dp=new int*[n];//动态申请二维数组nxm ;i<n;++i){ dp[i]=new int[m]; } 二.用malloc申请内存空间 ; ...
- C++中动态申请二维数组并释放方法
C/C++中动态开辟一维.二维数组是非常常用的,以前没记住,做题时怎么也想不起来,现在好好整理一下. C++中有三种方法来动态申请多维数组 (1)C中的malloc/free (2)C++中的new/ ...
- Python创建二维数组(关于list的一个小坑)
0.目录 1.遇到的问题 2.创建二维数组的办法 3.1 直接创建法 3.2 列表生成式法 3.3 使用模块numpy创建 1.遇到的问题 今天写Python代码的时候遇到了一个大坑,差点就耽误我交作 ...
随机推荐
- 笔记三、apache搭建gitweb【转】
参考文章: http://www.latelee.org/using-gnu-linux/ubuntu-apache-gitweb.html http://blog.csdn.net/ ...
- psycopg2.pool – Connections pooling / psycopg2.pool – 连接池 / postgresql 连接池
创建新的PostgreSQL连接可以是一个昂贵的操作.这个模块提供了一些纯Python类直接在客户端应用程序实现简单的连接池. class psycopg2.pool.AbstractCon ...
- struts配置。泪奔...
说多了都是泪啊,配置一个环境一天才搞定.不错the requested resource (/login) is not available in struts,就是找不到什么什么class.亦或th ...
- Python代码编辑器
PyCharm Community 说到PyCharm Community,我们就会想到它是一款免费的开源Python代码编辑器,不过这也是事实啦.PyCharm Community为我们提供了轻量级 ...
- [转载] 推荐的C++书籍以及阅读顺序
2014-06-17 转载自 oiramario 的文章 推荐的C++书籍以及阅读顺序 当读者有一定c/c++基础 推荐的阅读顺序: level 1 从<<essential c++> ...
- 关于android软键盘enter键的替换与事件监听
android软键盘事件监听enter键 软件盘的界面替换只有一个属性android:imeOptions,这个属性的可以取的值有 normal,actionUnspecified,actionNo ...
- 8皇后以及N皇后算法探究,回溯算法的JAVA实现,递归方案
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同 ...
- [ionic开源项目教程] - 第6讲 过滤器filter的使用
过滤器filter的使用 1.回顾 再熟悉一下tab1.html的代码: <div class="list"> <a ng-repeat="item i ...
- 30个实用的Linux find命令
除了在一个目录结构下查找文件这种基本的操作,你还可以用find命令实现一些实用的操作,使你的命令行之旅更加简易.本文将介绍15种无论是于新手还是老鸟都非常有用的Linux find命令 . 首先,在你 ...
- HDU 1728 逃离迷宫【BFS】
题意:给出一个起点,一个终点,规定的转弯次数,问能否在规定的转弯次数内到达终点--- 这一题是学(看)习(题)的(解)@_@ 主要学了两个地方 一个是剪枝,如果搜到的当前点的转弯次数小于该点turn数 ...