打印在类中创建的数组

时间:2019-02-10 11:10:53

标签: c++

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

#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

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

您创建本地数组,并将其第一个元素的地址分配给指针。但是当构造函数完成时,数组消失了,因此指针中存储的地址已经无效。

以“不确定行为”访问此地址,这意味着在运行该代码时可能发生任何事情。

处理此问题的最佳方法是使用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))
{
}

Init可以使用[][]而不是指针算术来方便访问。

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

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

就我个人而言,我认为命名常量比这更易读,但是它们将要求您永远不要更改向量的大小。如注释中所述,您还可以在需要它们的函数中本地创建此类常量。


您也可以使用动态内存分配,但是我不建议这样做。正确管理内存很困难,您将必须遵循Rule of Three/Five

答案 1 :(得分:0)

问题是您的阵列已被释放。

for(int n = 0; n < person.length; n++)
    {
        if(person[n].getSecId().contains("98"))
        {
            System.out.println(person[n].toString());s
            //delete this object from person array
        }
    }

相反,如πάντα ῥεῖ所正确建议的那样,您可以使用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

这被称为 RAII模式,它可以确保取消初始化。

修改

如果您不打算更改数组的尺寸,那么我强烈建议您使用Arr::~Arr() { delete[] ptr; }

std::array

答案 2 :(得分:0)

您可以使用构造函数中自动变量ptr的地址初始化指向整数arr2d的指针。自动变量在堆栈中分配,并且在离开代码作用域{ ... }的位置后自动销毁。因此,离开构造函数后,ptr中的地址不再有效,因为arr2d被破坏了。您可以在构造函数中使用动态内存分配

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

别忘了在析构函数中释放它:

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