将未知大小的2D数组传递给函数C ++

时间:2015-12-14 22:29:44

标签: c++ arrays function size

基本上,我的问题是:我让用户定义2D数组的大小(N,M)然后我声明:

int matrix [N] [M];

然后我需要将这个未初始化的矩阵传递给一个函数,该函数从.csv文件中读取一些数据并将其放入矩阵中,所以我尝试了:

void readwrite(int &matrix[N][], const int N, const int M){....};


int main(){
....
cin>>N;
cin>>M;

int matrix[N][M];
readwrite(matrix,N,M);
};

但是,当我编译它时,它会给我以下错误:" N未在此范围内声明"。

有关如何使这项工作的任何想法?

感谢y' all!

2 个答案:

答案 0 :(得分:0)

int &matrix[N][] - N必须是编译时常量,而不仅仅是const而不是参数。对数组的引用声明为:int (&matrix)[size]

尝试传递int **matrix,您还需要更改创建此数组的方式。 Variable lenght arrays are not supported in C++,你需要动态分配它的内存。或者更确切地说,如果您在编译时知道大小,请坚持使用std::vectorstd::array

答案 1 :(得分:0)

OP正在尝试的是如此令人烦恼地难以正确行动,与成本相比,拉动它的好处是微不足道的......好吧,我引用了经典。

  

唯一获胜的举动就是不参加比赛。

-Joshua,WarGames

您无法安全地将C ++中动态分配的2D数组传递给函数,因为您始终必须在编译时知道至少一个维度。

我可以在Passing a 2D array to a C++ function指出,因为这看起来很好。我赢了,因为它指的是静态分配的数组。

你可以玩愚蠢的投掷游戏来强制阵列进入函数,然后将其重新投射到内部。我不打算解释如何做到这一点,因为它是史诗级的愚蠢,应该是一个射击进攻。

您可以将指针传递给指针int **,但构造和销毁逻辑是一组奇怪的new和循环。此外,最终结果将分配的内存分散在RAM周围,从而削弱了处理器对预测和缓存的尝试。在现代处理器上,如果您无法预测和缓存,那么您将丢弃CPU的大部分性能。

你想做的是保持一维。一维阵列很容易通过。索引算法简单易行,易于预测。它是所有一个内存块,因此缓存命中的可能性更大。

制作一维阵列很简单:不要。请改用std::vector

std::vector<int> arr(rows*columns);

如果你必须,因为作业规范说&#34;没有载体!&#34;好吧,你被困住了。

int * arr = new int[rows*columns];

注意我使用rowscolumns而不是MN。面对MN哪个是哪个?谁知道,谁在乎,以及为什么首先要对自己这么做?为变量提供良好的描述性名称,并节省在以后调试时能够读取代码的时间。

使用的内容与数组和向量相同:

 int test = arr[row * columns + column];

将在[row][column]处恢复2D空间中的元素。我不应该解释这些变量的含义。死于MN

定义一个函数是:

void function (std::vector<int> & arr, size_t rows, size_t columns) 

或(yuck)

void function (int * arr, size_t rows, size_t columns) 

请注意,rowscolumns的类型为size_tsize_t是无符号的(负数组大小不是您想要的,所以为什么要允许它?)并且保证它足够大以容纳您可以使用的最大可能数组索引。换句话说,它比int更合适。但为什么到处都是rowscolumns?在这一点上要做的聪明的事情是围绕一个数组及其控制变量做一个包装,然后使用一些函数来使这个东西更容易使用。

template<class TYPE>
class Matrix
{
private:
    size_t rows, columns;
    std::vector<TYPE> matrix;
public: 
    // no default constructor. Matrix is BORN ready.

    Matrix(size_t numrows, size_t numcols):
        rows(numrows), columns(numcols), matrix(rows * columns)
    {
    }
// vector handles the Rule of Three for you. Don't need copy and move constructors
// a destructor or assignment and move operators

    // element accessor function
    TYPE & operator()(size_t row, size_t column)
    {
        // check bounds here
        return matrix[row * columns + column];
    }

    // constant element accessor function
    TYPE operator()(size_t row, size_t column) const
    {
        // check bounds here
        return matrix[row * columns + column];
    }

    // stupid little getter functions in case you need to know how big the matrix is
    size_t getRows() const
    {
        return rows;
    }
    size_t getColumns() const
    {
        return columns;
    }

    // and a handy-dandy stream output function
    friend std::ostream & operator<<(std::ostream &  out, const Matrix & in)
    {
        for (int i = 0; i < in.getRows(); i++)
        {
            for (int j = 0; j < in.getColumns(); j++)
            {
                out << in(i,j) << ' ';
            }
            out << '\n';
        }

        return out;
    }

};

粗略地说明阵列版本必须看起来只是为了展示允许vector执行其工作的好处。没有测试过。可能包含咆哮者。重点是更多的代码和更多的错误空间。

template<class TYPE>
class ArrayMatrix
{
private:
    size_t rows, columns;
    TYPE * matrix;
public:
    ArrayMatrix(size_t numrows, size_t numcols):
        rows(numrows), columns(numcols), matrix(new TYPE[rows * columns])
    {
    }

    // Array version needs the copy and move constructors to deal with that damn pointer
    ArrayMatrix(const ArrayMatrix & source):
        rows(source.rows), columns(source.columns), matrix(new TYPE[rows * columns])
    {
        for (size_t i = 0; i < rows * columns; i++)
        {
            matrix[i] = source.matrix[i];
        }
    }

    ArrayMatrix(ArrayMatrix && source):
        rows(source.rows), columns(source.columns), matrix(source.matrix)
    {
        source.rows = 0;
        source.columns = 0;
        source.matrix = nullptr;
    }

    // and it also needs a destructor
    ~ArrayMatrix()
    {
        delete[] matrix;
    }

    TYPE & operator()(size_t row, size_t column)
    {
        // check bounds here
        return matrix[row * columns + column];
    }

    TYPE operator()(size_t row, size_t column) const
    {
        // check bounds here
        return matrix[row * columns + column];
    }

    // and also needs assignment and move operator
    ArrayMatrix<TYPE> & operator=(const ArrayMatrix &source)
    {
        ArrayMatrix temp(source);
        swap(*this, temp); // copy and swap idiom. Read link below.
        // not following it exactly because operator=(ArrayMatrix source)
        // collides with operator=(ArrayMatrix && source) of move operator
        return *this;
    }

    ArrayMatrix<TYPE> & operator=(ArrayMatrix && source)
    {
        delete[] matrix;
        rows = source.rows;
        columns = source.columns;
        matrix = source.matrix;

        source.rows = 0;
        source.columns = 0;
        source.matrix = nullptr;

        return *this;
    }

    size_t getRows() const
    {
        return rows;
    }
    size_t getColumns() const
    {
        return columns;
    }
    friend std::ostream & operator<<(std::ostream &  out, const ArrayMatrix & in)
    {
        for (int i = 0; i < in.getRows(); i++)
        {
            for (int j = 0; j < in.getColumns(); j++)
            {
                out << in(i,j) << ' ';
            }
            out << std::endl;
        }

        return out;
    }

    //helper for swap.
    friend void swap(ArrayMatrix& first, ArrayMatrix& second)
    {
        std::swap(first.rows, second.rows);
        std::swap(first.columns, second.columns);
        std::swap(first.matrix, second.matrix);
    }

};

创建其中一个是

Matrix<int> arr(rows, columns);

现在传递数组是

void func(Matrix & arr);

使用数组是

int test = arr(row, column);

所有的索引数学都是隐藏的。

其他参考资料:

What is the copy-and-swap idiom?

What is The Rule of Three?