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

C++ 删除C+中动态创建的矩阵+;,c++,delete-operator,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 res

如何删除动态创建的矩阵?这很可能是重复的,对此我深表歉意,但到目前为止我真的找不到一个明确的答案。我初始化一个矩阵如下:

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;
        }
}
或者简单地说:

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

任何帮助/解释都将不胜感激。当运行deleteMatrix(M)时,这两个版本都“工作”,并且在控制台中没有向我显示任何错误,所以我感到困惑。谢谢

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

这些“2D数组”问题经常出现。我想我会回答一个问题

不要使用数组[]。不要使用
new[]
delete[]
。别这样。使用<代码> STD::向量< /代码>,让C++的奇迹为你做所有的更新和删除。或者对于一些严肃的事情,使用一个设计良好的开源库,比如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.
 }
#包括
使用std::size\u t;
模板
结构矩阵{
使用矩阵_type=std::vector;
矩阵_型矩阵;
矩阵(大小行、大小列)
:矩阵(行,矩阵类型::值类型(cols))
{}
};
int main(){
尺寸=5u;
尺寸=2u;
矩阵mx(nrow,ncol);
auto&matrix=mx.matrix;//现在使用矩阵[i][j]或其他任何形式。
//在这里,你可以用矩阵做任何你可以做的事情
//一个或多个数组…等等。它会在我自己之后清理。
}

正如许多其他人所说,每次您使用
新[]
时,您必须有一个匹配的
[]删除
。然而,就目前情况而言,您的函数以及它们的声明/定义方式,我相信您遇到了一个
X/Y
问题

这就是原因

您建议声明您的delete函数:您还声明这两个版本都可以工作并且没有显示任何错误。。。好吧,在你发布的问题中,两个版本完全相同

void deleteMatrix( float** M ) {
    // delete[] rows
    // delete[] cols
}
我在这里看到的问题是,当你传入一个指向浮点指针的指针时,函数不知道矩阵的维数。它可以是
2x2
2x3
3x2
3x3
MxN
等。在不知道矩阵尺寸的情况下,如何编写for循环来遍历内部或嵌套数组?您必须将这些维度传递到delete函数:

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

编辑-我回顾了我的库中的一些类,这里是一个模板矩阵类,我用任何尺寸的矩阵
MxNx…ith
编写,它在易用性和使用性方面非常通用。如果需要,您可以扩展它:我没有做任何
类型
检查或
断言
,但可以轻松添加

使用它非常简单:

#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.inl

我没有演示
numElements()
stride()
函数的使用,但它们应该是非常自解释的。Stripes函数是一个非常好的功能,因为如果用户调用模板,就会得到一个
1x3x5
矩阵;它们存储在
\u跨步
成员向量中。这样,您就可以始终拥有每个维度大小所需的索引

现在如果你想把矩阵放在堆上;与尝试执行
双指针
[]]
并将每个元素放在堆上不同,使用此类您有两个选项

您可以直接将实例化的对象放在堆上,也可以让这个类保存堆对象

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.
std::共享\u ptr ptrMat2x2;//矩阵的堆指针
矩阵mat3x3ptrs;//堆对象的矩阵。
乍一看,代码可能有点奇怪,但这表明这两种情况都可以做到:

#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;
}
#包括
#包括“矩阵h”
int main(){
//通过共享ptr在堆上创建矩阵`
std::共享的ptr ptrMat2x2=
标准::使_共享(矩阵(1,2,3,4));
//从共享指针访问元素并打印
对于(int i=0;i<4;i++)

std::cout可能重复的最后两个代码块是相同的
结果
永远不会返回。如果第二个新[]抛出异常,则会导致内存泄漏。将函数放在一行中,更好:
std::vector Your_矩阵(Nrows*Ncols)这里的分配方式和我们不一样:我们只有两个分配。除了C++中不需要的以外,删除函数中的OP代码没有什么错。有优势的是不需要知道行数。重要的是分配是按OP方式进行的。正在进行分配。一个分配给行指针,另一个分配给整个数据。如果列数相同,则将分配/取消分配的数量减少到2个调用,而不是
number of_rows+1
调用。另一个优点是数据是连续的,而不是分散的。@PaulMcKenzie是的,这是有道理的;但是我一直在思考如何调用
[]删除
行和列,因为
float**M
是在不知道矩阵的维度的情况下传递的。起初我觉得这是一个x/y问题。@PaulMcKenzie如果你有
[I][j]
在堆上。那么在删除外部指针数组之前,您不必遍历每个
[j]
来删除堆上的每个数组?换句话说:调用
delete[]M[0]
可以为您的应用程序执行此操作吗?如果您在一次分配中拥有堆上的全部数据,那么是的,不需要循环。请参阅以获得更好的解释。@PaulMcKenzie好的,这确实澄清了一些问题,关于答案显示如何删除池,然后删除指针。我认为这已经开始出现了
#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
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];
}
#include "Matrix.h"
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;
}