在C ++中删除动态创建的矩阵

时间:2018-04-04 00:53:37

标签: c++ delete-operator

如何删除动态创建的矩阵?这可能是重复的,我为此道歉,但到目前为止我真的找不到明确的答案。我按如下方式初始化矩阵:

float ** createMatrix(unsigned int Nrows, unsigned int Ncols) {
    float ** result = NULL;

    if (Nrows != 0 && Ncols != 0) {
        // create the matrix on the heap
        result = new float * [Nrows];
        result[0] = new float [Nrows*Ncols]();

        // link the rows
        for (int i = 1; i < Nrows; i++) {
            result[i] = result[i-1] + Ncols;
        }
}

现在,我想创建一个删除它的函数。我需要两个单独的语句来删除M [0]和M,还是只需要一个M?即我需要:

void deleteMatrix(float **M){
    delete[] M[0];
    delete[] M;
}

或简单:

void deleteMatrix(float **M){
    delete[] M;
}

任何帮助/解释都会受到大力赞赏。当deleteMatrix(M)运行时,两个版本都“工作”并且在控制台中没有显示任何错误,所以我很困惑。谢谢!

3 个答案:

答案 0 :(得分:1)

这些&#34; 2D阵列&#34;问题不断出现。我想我会回答一个。

不要使用数组[]。请勿使用new[]delete[]。只是不要。使用std::vector<std::vector<int>>让C ++的奇迹为你做所有新的和删除。或者对于严肃的事情,使用设计良好的开源库,如boost::matrix. C ++是很酷的。

以下是入门套件。它可以通过多种方式得到改善,私有化和抽象化。

#include <vector>
using std::size_t;

template<class T>
struct Matrix {
    using matrix_type = std::vector<std::vector<T>>;
    matrix_type matrix;
    Matrix(size_t rows, size_t cols)
        : matrix(rows, matrix_type::value_type(cols)) 
    {}
};

int main() {
    size_t Nrows = 5u;
    size_t Ncols = 2u;
    Matrix<int> mx(Nrows, Ncols);

    auto& matrix = mx.matrix;  // Now use matrix[i][j] or whatever.

    // Here you can do anything with matrix that your could do with 
    // an array  or arrays ... and more. And it cleans up after iself.
 }

答案 1 :(得分:1)

正如许多其他人在每次使用new[]时所说的那样,您必须拥有匹配的[] delete。但是,由于它目前支持您的功能以及如何声明/定义它们,我相信您遇到了X/Y问题。

这就是为什么!

你建议你这样声明你的删除功能:你还说这两个版本都有效,并且没有显示任何错误......在你发布的问题中,两个版本完全一样......

void deleteMatrix( float** M ) {
    // delete[] rows
    // delete[] cols
}

我在这里看到的问题是,当你传入指向浮点指针的指针时,该函数不知道矩阵的维数。它可以是2x22x33x23x3MxN等。如果不知道矩阵的维度,你怎么能写出for循环遍历内部或嵌套数组?您必须将这些维度传递给删除功能:

void deleteMatrix( float** M, int rowSize, int colSize ) {
    for ( int row = 0; row < rowSize; row++ ) {
        delete [] M[i];
    }
    delete [] M;
}

以下示例与您尝试实施的内容类似:thispointer.com

在你的实际问题之外;这往往更像是C方法或过时的C ++方法。不建议使用原始指针和新的&amp;自由删除。使用智能指针更好。但是对于像矩阵类这样的构造,有很多可以自由使用的库已经定义了这样的类 - 使用的接口和一些最流行的类:

修改 - 用户PaulMcKenzie清除了一个我早已忘记的有效点,因为我主要使用vector<object>vector<shared_ptr<object>>。自从我第一次学习指针 - 多维数组并且我已经忘记了关于连续数组的概念以来已经超过15年了。他在评论部分发给我的问题的答案清楚地解释了我忘记了什么;找到here。如果数组在内存中不连续,那么是的X/Y问题不知道它们的维度,但是因为它们是;不需要知道尺寸。而你已经提出的建议应该有效:

void deleteMatrix(float **M){
    delete[] M[0];
    delete[] M;
}

编辑 - 我正在浏览我的库中的一些类,这里是一个模板矩阵类,我用任何维度矩阵MxNx...ith编写它它的易用性和使用非常灵活。如果您愿意,可以对其进行扩展:我没有进行任何type检查或assertions,但可以轻松添加。

使用它就像:

#include <iostream>
#include "Matrix.h"

int main() {
    Matrix<int, 2, 2> imat3x3( 1, 2, 3, 4, 5, 6, 7, 8, 9 );

    // calling elements() and using vector's [] operator
    for ( int i = 0; i < 9; i++ )
        std::cout << imat3x3.elements()[i] << ' ';            
    std::cout << '\n';

    // Using class's [] operator
    for ( int i = 0; i < 9; i++ )
        std::cout << imat3x3[i] << ' ';
    std::cout << '\n';

    // Using class's () operator
    for ( int i = 0; i < 9; i++ )
        std::cout << imat3x3(i) << ' ';
    std::cout << '\n';

    // Okay that was a 3x3 matrix of ints, lets do a 2x2x2 matrix of floats
    Matrix<float,2,2,2> fmat2x2x2( 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f );

    // now the operators
    for ( int i = 0; i < 8; i++ ) {
        std::cout << fmat2x2x2[i] << "f ";
    std::cout << '\n';

    for ( int i = 0; i < 8; i++ ) {
        std::cout << fmat2x2x2(i) << "f ";
    std::cout << '\n';          

    std::cout << "\nPress any key and enter to quit.\n";
    std::cin.get();
    return 0;
}

Matrix.h

#ifndef MATRIX_H
#define MATRIX_H

#include <vector>
#include <algorithm>
#include <numeric>

template<typename Type, size_t... Dims>
class Matrix {
public:
    static const size_t _numDims = sizeof...(Dims);

private:
    size_t _numElements;

    std::vector<Type>   _elements;
    std::vector<size_t> _strides;

public:
    Matrix() noexcept;

    template<typename... Args>
    Matrix( Args&&... args ) noexcept;

    const Type& operator[]( size_t idx );
    const Type operator[]( size_t idx ) const;

    const Type& operator() ( size_t idx );
    const Type operator() ( size_t idx ) const;

    size_t numElements() const {
        return _elements.size();
    }

    const std::vector<size_t>& strides() const {
        return _strides;
    }

    const std::vector<Type>& elements() const {
        return _elements;
    }
};    

#include "Matrix.inl"

#endif // !MATRIX_H

Matrix.inl

template<typename Type, size_t... Dims>
Matrix<Type, Dims...>::Matrix() noexcept :
_strides( { Dims... } ) {
    using std::begin;
    using std::end;
    auto mult = std::accumulate( begin( _strides ), end( strides ), 1, std::multiplies<>() );
    _numElements = mult;
    _elements.resize( _numElements );
}

template<typename Type, size_t... Dims>
template<typename... Args>
Matrix<Type, Dims...>::Matrix( Args&&... args ) noexcept :
_elements( { args... } ),
_strides( { Dims... } ) {
    _numElements = _elements.size();
}

template<typename Type, size_t... Dims>
const Type Matrix<Type, Dims...>::operator[]( size_t idx ) const {
    return _elements[idx];
}

template<typename Type, size_t... Dims>
const Type& Matrix<Type, Dims...>::operator[]( size_t idx ) {
    return _elements[idx];
}

template<typename Type, size_t... Dims>
const Type Matrix<Type, Dims...>::operator()( size_t idx ) const {
    return _elements[idx];
}

template<typename Type, size_t... Dims>
const Type& Matrix<Type, Dims...>::operator()( size_t idx ) {
    return _elements[idx];
}

Matrix.cpp - 这个cpp文件不是必需的我只需要在调试类的基本编译器错误时轻松编译它

#include "Matrix.h"

我没有证明使用numElements()stride()函数,但它们应该是相当自我解释的。 strides函数是一个非常好的功能,因为如果用户调用模板<type, 1,3,5>给你一个1x3x5矩阵;这些存储在_strides成员向量中。这样,您始终可以获得每个维度大小所需的索引。

现在,如果你想要你的矩阵在堆上;而不是尝试执行double pointer[][]并将每个元素放在堆上,使用此类有两个选项。

您可以直接将实例化对象放在堆上,也可以让此类同时保存堆对象。

std::shared_ptr<Matrix<int,2,2>> ptrMat2x2; // A heap pointer of the matrix
Matrix<shared_ptr<int>,3,3> mat3x3ptrs; // A matrix of heap objects.

乍一看代码看起来有点奇怪,但这表明两种情况都可以完成:

#include <iostream>
#include "Matrix.h"

int main() {
    // A Matrix<> on the heap via shared_ptr`
    std::shared_ptr<Matrix<int, 2, 2>> ptrMat2x2 =
      std::make_shared<Matrix<int, 2, 2>>( Matrix<int,2,2>( 1, 2, 3, 4 ) );

    // accessing the elements from the shared pointer and printing
    for( int i = 0; i < 4; i++ ) 
        std::cout << (*ptrMat2x2.get())(i) << ' ';
    std::cout << '\n';

    // creating some basic shared_ptrs 
    auto a = std::make_shared<int>( 1 );
    auto b = std::make_shared<int>( 2 );
    auto c = std::make_shared<int>( 3 );
    auto d = std::make_shared<int>( 4 );
    // Matrix that holds shared_ptrs
    Matrix<std::shared_ptr<int>, 2, 2> mat2x2ptrs( a, b, c, d );

    // print the elements from the matrix (don't forget to dereference).
    for( int i = 0; i < 4; i++ )
        std::cout << *mat2x2ptrs[i].get() << ' ';
    std::cout << '\n';

    std::cout << "\nPress any key and enter to quit.\n";
    std::cin.get();
    return 0;
}

答案 2 :(得分:0)

您已经分配了两个单独的数组,您需要以相反的顺序删除两个单独的数组。