1

当我从用户那里读取一些值并且我需要创建一个特定大小的数组时,我会这样做:

#include <iostream>
using namespace std;    
unsigned* numbers;
int main()
{
int a;
cin >> a;
numbers = new unsigned[a];
}

如何使用 2d 数组(从用户读取的大小为 a*b)来做到这一点?

4

8 回答 8

7

如果 a 和 b 分别是行数和列数,您可以像这样分配数组:

new unsigned[a * b];

要访问 rowi和 column的元素j,请执行以下操作:

numbers[i * b + j]

但是,请注意,实际上你几乎肯定会更好地使用std::vector你想要做的任何事情,但你可能还没有了解这一点:)

于 2013-01-11T10:09:49.033 回答
6

任何在代码中看起来像二维数组的东西都不会是内存中的物理二维数组,而是一个普通的内存块或分散的内存块,具体取决于您如何分配它。

  • 您可以通过在另一个 N 指针的动态数组中动态分配 N 数组来折磨自己,就像 nrussel 的回答所暗示的那样。
  • 你可以创建一个向量向量,就像 billz 和 Arun CB 建议的那样——这可以让你从自己管理分配的内存中解脱出来,但仍然会给你留下 N+1 个分散的分配,这不是很好的性能。
  • Brennan Vincent 的回答建议分配一个包含 a*b 元素的动态数组,这会在内存中为您提供一个连续的块。将其与他提到的内置动态内存管理相结合,std::vector并感到高兴:

    std::vector<unsigned> matrix(a*b);

如果您希望矩阵方便访问,请将整个事物包装到一个类中,以便您访问具有 2D 坐标的元素。但请不要自己管理内存。它只会伤害您和任何必须维护该代码(并搜索内存泄漏)的人。

于 2013-01-11T10:20:49.113 回答
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;
于 2013-01-11T10:11:01.773 回答
3

更新推荐:

值得注意的是,boost 已经做到了这一点。所以我会坚持下去,如果它不打算封装在一个类中。

原答案:

通常,使用原始数组和分配不如使用std::vector. 现在,您当然可以使用vector<vector<T>>,但这不仅打字太长,而且还可能涉及不必要的复制。

使用ptr_vectororvector<unique_ptr<vector<int>>会解决第二个问题,但会使事情变得更糟。那么如何解决呢?

很简单:根本不要使用二维数组

想象一下内存中的二维数组:

[X|X|X|X]
[Y|Y|Y|Y]
[Z|Z|Z|Z]

很明显,它可以放在一行中:

[X|X|X|X|Y|Y|Y|Y|Z|Z|Z|Z]

现在我们回到旧的、熟悉的一维数组(不管它是vectorC 样式数组还是 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;

返回引用以允许以与普通二维数组非常相似的方式使用一维结构:

// 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允许一侧无限增长)。这可能最好通过在编译时创建适当的访问函数来完成,计算

i = 0 i < n (大小i ) i * D i ,

其中 n 是维数,S 是维数数组,D 是坐标数组。

于 2013-01-11T10:22:41.673 回答
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;
   }
}
于 2013-01-11T10:16:55.067 回答
1

您可以通过以下方式使用 c++ new[] 分配内存:

int** array = new int*[x];
for(int i = 0; i < x; i++)
    aryay[i] = new int[y];

简单的概念是它和指向数组的指针数组。它也必须删除以避免内存泄漏。

于 2013-01-11T10:32:52.657 回答
1

尽管“向量的向量”解决方案可以令人满意,但它们不是 2D 结构:每个“行”将独立分配,并且长度可以逐行不同(因此必须手动维护 2D 约束:插入一个项目需要放大所有行,以便一个在另一个之上的元素保持它们的相对位置。

如果您需要一个适当的动态 2D 结构,您可以将一个向量(简单的一维)包装在一个类中(我们称之为“ table”),并为该类提供操作要求,以将其正确地维护为一个外部表示的 2D。尤其:

  • 定义一个Colums() constRows() const函数来重新调整表的实际大小。
  • 定义 aint& operator()(unsigned row, unsigned col) { return vect[row*Colums()+col]; }和它的 const 对应项
  • 定义一个struct coord { unsigned r, unsigned c }和一个方便table::operator[](const coord&)
  • 定义insertremove插入一行(只需在 处插入Colums()连续元素r*Columns())和一列(Columns()+1从 开始插入一个元素c)的方法
  • 定义适当的迭代器类,这些迭代器类沿着列(++ 前进 1 个元素)和行(++ 前进由 Colums() 元素)(注意始终end()为它们定义一个值)

所有这些东西的关键是对n = r*C+c第二点公式的理解。其他一切都只是一个几乎直接的后果。

于 2013-01-11T10:42:04.260 回答
0
unsigned **numbers;
numbers = new unsigned*[a];
for (int i=0; i<a; i++){
    numbers[i] = new unsigned[b];
}

它的行为与二维数组不完全相同,因为它在内存中不连续,但它会这样做。您还可以使用符号numbers[i][j]来访问元素。

记住在-ing本身之前最后delete[]的每个元素numbersdelete[]numbers

使用std::vector可能是一个更可取的解决方案,如其他帖子中所述

于 2013-01-11T10:08:36.787 回答