当我从用户那里读取一些值并且我需要创建一个特定大小的数组时,我会这样做:
#include <iostream>
using namespace std;
unsigned* numbers;
int main()
{
int a;
cin >> a;
numbers = new unsigned[a];
}
如何使用2d数组(从用户读取大小a * b)?
答案 0 :(得分:7)
如果a和b分别是行数和列数,则可以像这样分配数组:
new unsigned[a * b];
要访问第i
行和第j
行的元素,请执行以下操作:
numbers[i * b + j]
然而,请注意,实际上,对于您正在尝试的任何内容,使用std::vector
几乎肯定会更好,但您可能还没有了解到这一点:)
答案 1 :(得分:6)
任何在代码中看起来像2D数组的东西都不会是内存中的物理2D数组,而是一个普通的内存块或分散的内存,具体取决于你如何分配它。
Brennan Vincent的回答建议分配一个包含* b元素的动态数组,它会在内存中为你提供一个连续的块。将其与他提到的std::vector
的内置动态内存管理相结合,并感到高兴:
std::vector<unsigned> matrix(a*b);
如果您希望矩阵方便访问,请将整个事物包装到一个类中,以便您可以访问具有2D坐标的元素。但请远离自己管理内存。它只会伤害你和任何必须维护该代码(并搜索内存泄漏)的人。
答案 2 :(得分:3)
可以使用一个向量来表示两个维度数组:
typedef std::vector<int> d1_type; // 1D
typedef std::vector<d1_type> d2_type; // 2D
typedef std::vector<d2_type> d3_type; // 3D
int num = 5;
d2_type value2d(num, d1_type(num));
d3_type value3d(num, d2_type(num, d1_type(num)));
您可以访问2D / 3D矢量数组,例如:
value2d[0][0] = 100;
value3d[0][0][0] = 100;
答案 3 :(得分:3)
值得注意的是boost already did that.所以我只会坚持下去,如果它不打算封装在一个类中。
通常,使用原始数组和分配不如使用std::vector
。现在,您当然可以使用vector<vector<T>>
,但这不仅仅是键入的长度,还可能涉及不必要的复制。
使用ptr_vector
或vector<unique_ptr<vector<int>>
可以解决第二个问题,但事情会更加复杂化。那怎么解决呢?
很简单:根本不使用2D数组。
想象你的2D数组在内存中:
[X|X|X|X]
[Y|Y|Y|Y]
[Z|Z|Z|Z]
很明显它可以放在一行中:
[X|X|X|X|Y|Y|Y|Y|Z|Z|Z|Z]
现在我们回到旧的,熟悉的一维数组(无论是vector
还是C风格的数组都无关紧要)。为了获得你的元素,你必须知道你的初始数组的宽度,并转到对应于第n行的数组元素,然后明确地添加列数:
int& access (unsigned x, unsigned y) {
return data[x * sizeY + y]; // Or (y * sizeX + x)
}
由于它是存根方法,因此实际使用中可能存在问题。以下是全局实施的示例:
int& accessVectorAs2d (std::vector<int> & data, unsigned x, unsigned y, unsigned int sizeY); // inside stays the same
unsigned SizeX = 20, SizeY = 20;
std::vector<int> V (SizeX * SizeY, 0);
accessVectorAs2d(V, 1, 3, SizeX) = 5;
返回引用以允许以与普通2D数组非常类似的方式使用您的1D结构:
// So you can do either reads
int X = access(1, 3);
// Or writes!
access(1,3) = 5;
附加说明:如果您构建自己的类,重载operator()
可以为您带来更好的结果:
Data(1, 3) = 5;
int X = Data(1, 3);
现在你将如何实现该访问(子类化或封装向量,或仅使用普通的全局函数)并不重要。
我强烈建议你在这里使用std::vector
。它将确保没有内存泄漏(忘记删除),更容易更改大小(通过.push_back()
或.reserve()
),并且通常是建议的做法;毕竟,你是用C ++编写的,而不是用C语言编写的。
实际上,这个类当然应该是模板化的,不仅有类型,还有维度的数量(好的,可以简化)和(每1个)维度的大小(-1允许一侧无限增长) )。通过在编译时创建适当的访问函数,计算
,这可能是最好的Sum i = 0 i&lt; n (大小 i ) i * D i ,
其中n是维数,S是维度大小的数组,D是坐标数组。
答案 4 :(得分:2)
尝试使用矢量。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
// An empty vector of vectors. The space
// between the 2 '>' signs is necessary
vector<vector<int> > v2d;
// If you intend creating many vectors
// of vectors, the following's tidier
typedef vector<vector<int> > IntMatrix;
IntMatrix m;
// Now we'll try to create a 3 by 5 "matrix".
// First, create a vector with 5 elements
vector<int> v2(5, 99);
// Now create a vector of 3 elements.
// Each element is a copy of v2
vector<vector<int> > v2d2(3,v2);
// Print out the elements
for(int i=0;i<v2d2.size(); i++) {
for (int j=0;j<v2d2[i].size(); j++)
cout << v2d2[i][j] << " ";
cout << endl;
}
}
答案 5 :(得分:1)
您可以通过以下方式使用c ++ new []分配内存:
int** array = new int*[x];
for(int i = 0; i < x; i++)
aryay[i] = new int[y];
这个简单的概念是它和指向数组的指针数组。必须删除它以避免内存泄漏。
答案 6 :(得分:1)
虽然“矢量矢量”解决方案可以令人满意,但它们不是2D结构:每个“行”将独立于另一个分配,并且长度可以逐行不同(因此必须保持2D约束)手动:插入一个项目需要放大所有行,以便一个在另一个之上的元素保持其相对位置。
如果你需要一个合适的动态2D结构,你可以将一个向量(简单的单维)包装在一个类中(让我们称之为“table
”)并为该类提供操作requird以正确维护它作为外部代表的2D。特别是:
Colums() const
和Rows() const
函数,重新调整表格的实际大小。int& operator()(unsigned row, unsigned col) { return vect[row*Colums()+col]; }
和它的const对应struct coord { unsigned r, unsigned c }
和方便的table::operator[](const coord&)
insert
和remove
方法以插入行(只需在Colums()
处插入r*Columns()
个}元素)和一列(每Columns()+1
插入一个元素从c
开始end()
值)所有这些内容的关键点是在第二点理解n = r*C+c
公式。其他一切只是一个近乎直接的结果。
答案 7 :(得分:0)
unsigned **numbers;
numbers = new unsigned*[a];
for (int i=0; i<a; i++){
numbers[i] = new unsigned[b];
}
它的行为与二维数组完全不同,因为它在内存中不连续,但它会这样做。您还可以使用符号numbers[i][j]
来访问元素。
在delete[]
- numbers
本身
delete[]
numbers
的每个元素std::vector
使用{{1}}可能是一个更好的解决方案,详见其他帖子