To pass the task, I need for each new, after use, perform delete. In this part of the code, I call new for each line of the matrix — and then the allocated memory is not released. Where to put delete? I tried after std :: fill to write delete [] matrix [i], but it gives an error.

template<class T> T** createMatrix(int ncount, int mcount) { T** matrix = new T*[ncount]; for (int i = 0; i < ncount; ++i) { matrix[i] = new T[mcount]; std::fill(matrix[i], matrix[i] + mcount, T()); } return matrix; 

    2 answers 2

    Where to put delete?

    In your case, you must provide a special function releaseMatrix(ncount, matrix); in which will be what Denis Rakitin wrote

    And in an amicable way, to the Matrix type wrapper destructor, which will own the pointers. When a Matrix object dies (exit from a method, the death of the owner class whose member was a Matrix object or an exception in general), then the memory is also freed. RAII

     template<typename T> class Matrix { public: typedef T value_type; typedef size_t dim_size; Matrix(dim_size n, dim_size m) : _n(n), _m(m), _buffer(new T[ n * m ]) { } ~Matrix() { delete [] _buffer; } dim_size getRowsCount() const { return _n; } dim_size getColsCount() const { return _m; } T& at(dim_size row, dim_size col) { return _buffer[ row * _m + col ]; } private: const int _n, _m; T *_buffer; Matrix(const Matrix<T>& other) =delete; Matrix(Matrix<T>&& other) =delete; Matrix& operator=(const Matrix<T>& other) =delete; Matrix& operator=(Matrix<T>&& other) =delete; }; 

    Or just use a smart pointer with custom deleter:

     template<class T> using MatrixPtr = std::unique_ptr<T**,std::function<void(T***)>; template<class T> MatrixPtr& createMatrix(int ncount, int mcount) { T **matrix = new T*[ncount]; for (int i = 0; i < ncount; ++i) { matrix[i] = new T[mcount]; // допустим, что мы не боимся std::bad_alloc std::fill(matrix[i], matrix[i] + mcount, T()); } return MatrixPtr(matrix, [ncount](T ***matrix) { for (int i = 0; i < ncount; ++i) { delete[] *matrix[i]; } delete[] *matrix; }); } 
    • Regarding RAII: if the constructor crashes a memory shortage somewhere in the loop, there will still be a leak. Therefore, it should be a single block, it is useful for performance. Oh .. I didn’t immediately notice that this is how it is with you :) Although you can completely get rid of the destructor by using unique_ptr as a member. - αλεχολυτ
    • Here you only altered the data structure ... Perhaps, an array of pointers is needed for something (it is unlikely for the author in this task, but in the general case this happens) - avp
    • @avp, yes, of course, in the second case I redid it quite consciously. If necessary, the code can be subjected to a slight tuning and get the desired interface to the data, without losing the convenience of "semi-automatic" memory management. - free_ze
    • @free_ze you have in the first case due to the fact that the rule of three is not taken into account will be segmentation failt for example, if you assign the first matrix to the second and delete after this second and then refer to the first. - ampawd
    • @arammis, thanks, obviously disconnected, so as not to clutter up the code. - free_ze pm
      for (int i = 0; i < ncount; ++i) delete[] matrix[i]; delete[] matrix; 

    But there is no point in doing this in createMatrix.