打印在类中创建的数组

Printing arrays created in a class

本文关键字:数组 创建 打印      更新时间:2023-10-16

我正在尝试打印在类初始值设定项中创建的数组。我尝试了很多方法,但我的发现是,我必须使用指针来解决这个问题。代码:

#include <iostream>
// arr.h
class Arr
{
private:
const int sizeVertical;
const int sizeHorizontal;
int *ptr;
public:
Arr(int sizeVertical, int sizeHorizontal);
void Init();
void Print();
};
// arr.cpp
Arr::Arr(int _sizeVertical, int _sizeHorizontal)
:   sizeVertical(_sizeVertical),
sizeHorizontal(_sizeHorizontal)
{
int arr2d[sizeVertical][sizeHorizontal];
ptr = &arr2d[0][0];
}
void Arr::Init()
{
for(int i=0; i<sizeVertical; i++)
{
for(int j=0; j<sizeHorizontal; j++)
{
*(ptr + i * sizeHorizontal + j) = i+j;
}
}
}
void Arr::Print()
{
for(int i=0; i<sizeVertical; i++)
{
for(int j=0; j<sizeHorizontal; j++)
{
std::cout<<*(ptr + i * sizeHorizontal + j)<<std::endl;
}
}
}
// main.cpp
int main()
{
Arr test(4,3);
test.Init();
test.Print();
}

在我定义数组的方法(Init)中,我也可以用与方法(print)中相同的方式打印数组。但是,当尝试用不同的方法打印数组时,输出看起来非常奇怪。输出:

0
22025
955388640
32767
10
0
-1247975061
32668
1
3
-1549041632
22025

有什么想法吗?

创建本地数组,并将其第一个元素的地址分配给指针。但当构造函数完成时,数组就不见了,所以存储在指针中的地址已经无效。

在Undefined Behavior中访问此地址,这意味着当您运行该代码时,任何事情都可能发生。

处理此问题的最佳方法是使用std::vector<std::vector<int>>,如评论中所建议的:

#include <vector>
class Arr
{
private:
const int sizeVertical;
const int sizeHorizontal;
std::vector<std::vector<int>> arr2d;
public:
Arr(int sizeVertical, int sizeHorizontal);
void Init();
void Print();
};
// arr.cpp
Arr::Arr(int _sizeVertical, int _sizeHorizontal)
:   sizeVertical(_sizeVertical),
sizeHorizontal(_sizeHorizontal),
arr2d(_sizeVertical, std::vector<int>(_sizeHorizontal))
{
}

CCD_ 2可以使用CCD_。

请注意,您不再需要sizeVerticalsizeHorizontal,您可以使用arr2d.size()arr2d[0].size()

for(int i=0; i<arr2d.size(); i++)
{
for(int j=0; j<arr2d[0].size(); j++)
{
}
}

就我个人而言,我认为命名常数比这个更可读,但它们要求你永远不要改变向量的大小。正如注释中所指出的,您也可以在需要的函数中本地创建这样的常量。


您也可以使用动态内存分配,但我不建议这样做。很难正确管理内存,你必须遵循三/五规则

在构造函数中使用自动变量arr2d的地址初始化指向intptr的指针。在堆栈中分配的自动变量,一旦离开分配它们的代码范围{ ... },就会自动销毁。因此,在您离开构造函数之后,ptr中的地址将不再有效,因为arr2d已被销毁。您可以在构造函数中使用动态内存分配

Arr::Arr(int _sizeVertical, int _sizeHorizontal)
:   sizeVertical(_sizeVertical),
sizeHorizontal(_sizeHorizontal)
{
ptr = new int[sizeVertical * sizeHorizontal];
}

不要忘记在析构函数中释放它:

Arr::~Arr(void)
{
delete[] ptr;
}

问题是您的数组已被解除分配。

Arr::Arr(int _sizeVertical, int _sizeHorizontal)
:   sizeVertical(_sizeVertical),
sizeHorizontal(_sizeHorizontal)
{
int arr2d[sizeVertical][sizeHorizontal]; // arr2d allocated.
ptr = &arr2d[0][0];
} // arr2d dies here

相反,正如πάΓτα正确地提出的那样ῥεῖ,您可以使用std::vector< std::vector<int> >。如果你不想这样做,你可以使用动态内存,尽管我不推荐它

Arr::Arr(int _sizeVertical, int _sizeHorizontal)
:   sizeVertical(_sizeVertical),
sizeHorizontal(_sizeHorizontal)
{
ptr = new int[sizeVertical * sizeHorizontal];
}

确保通过在析构函数中设置delete来释放分配给它的动态内存。

Arr::~Arr()
{
delete[] ptr;
}

这被称为RAII模式,它保证了去初始化。

编辑

如果您不打算更改数组的维度,那么我强烈建议您使用std::array

#include <iostream>
#include <array>
template<int sizeVertical, int sizeHorizontal>
class Arr
{
private:
std::array<std::array<int, sizeHorizontal>, sizeVertical> arr;
public:
Arr() { }
void Init() {
for (int i = 0; i < sizeVertical; i++) {
for (int j = 0; j < sizeHorizontal; j++) {
arr[i][j] = i + j;
}
}
}
void Print() {
for (int i = 0; i < sizeVertical; i++) {
for (int j = 0; j < sizeHorizontal; j++) {
std::cout << arr[i][j] << " ";
}
std::cout << "n";
}   
}
};
int main()
{
Arr<10, 2> arr;
arr.Init();
arr.Print();
}