簡體   English   中英

關於3D數組在C++中動態memory分配的問題

[英]Question about Dynamic memory allocation in C++ for 3D array

我想寫一個函數來創建一個 3D 矩陣,但是當我嘗試顯示它時遇到了問題,請幫助我,謝謝。

我的老師給了我他的代碼。他的代碼可以創建一個具有動態 memory 的二維數組,我想更改他的代碼以創建一個 3D 矩陣。 當我試圖顯示矩陣時,我意識到我創建的數組是一個二維數組,而且因為我剛開始使用 C++,所以我找不到我的錯誤。

/*<Array3D.h>*/
#pragma once
#ifndef _ARRAY_3D_H_
#define _ARRAY_3D_H_

//-----------------------------------------
#include <cassert>
#include <vector>
using namespace std;

template<typename T>
class Array3D
{
public:
    typedef Array3D<T> _Myt;
    Array3D()
        : m_nRows(0)
        , m_nCols(0)
        , m_nDepths(0)
    {}

    Array3D(size_t r, size_t c,size_t d)
    {
        Resize(r, c, d);
    }

    //Allocating memory size
    void Resize(size_t r, size_t c,size_t d)
    {
        if (r == m_nRows && c == m_nCols && d==m_nDepths) { return; }

        bool bValid = r > 0 && c > 0 && d>0;
        if (!bValid) return;

        m_nRows = r;
        m_nCols = c;
        m_nDepths = d;
        m_v.resize(m_nRows * m_nCols * m_nDepths);
    }

    const T* operator[](size_t r) const
    {
        assert(r >= 0 && r < m_nRows);
        return &(*(m_v.begin() + (r * m_nCols * m_nDepths)));
    }

    T* operator[](size_t r)
    {
        assert(r >= 0 && r < m_nRows);
        return &(*(m_v.begin() + (r * m_nCols * m_nDepths)));
    }

    //Gets the start position of a one-dimensional array
    const T* GetRawPointer() const { return &(m_v[0]); }
          T* GetRawPointer() { return &(m_v[0]); }

    long Rows() const
    {
        return static_cast<long>(m_nRows);
    }

    long Cols() const
    {
        return static_cast<long>(m_nCols);
    }

    long Depths() const
    {
        return static_cast<long>(m_nDepths);
    }

    long TotalSize() const
    {
        return static_cast<long>(m_nRows * m_nCols * m_nDepths);
    }

    void ClearUp()
    {
        m_nRows = 0;
        m_nCols = 0;
        m_nDepths = 0;
        m_v.clear();
    }

    bool IsEmpty() const { return m_v.empty(); }

protected:
    vector<T>   m_v;//  Internally a one-dimensional  is used
    size_t      m_nRows; 
    size_t      m_nCols; 
    size_t      m_nDepths; 
};

<Matrix3D.h>
#pragma once
#include "Array3D.h"
class Matrix3D
{
public:
    Matrix3D(int r = 0, int c = 0, int d = 0)
    {
        setSize(r, c, d);
    }

    void setSize(int r, int c, int d) { m_data3D.Resize(r, c, d); }
    void clear() { m_data3D.ClearUp(); }

    int rows() const { return m_data3D.Rows(); }
    int cols() const { return m_data3D.Cols(); }
    int Depths() const { return m_data3D.Depths(); }

    void display() const;

    //Operator Overloading
    float* operator[](int rIndex) { return m_data3D[rIndex]; }
    const float* operator[](int rIndex) const { return m_data3D[rIndex]; }

private:
    Array3D<float> m_data3D;
};
#include "Matrix3D.h"
#include <iostream>
using namespace std;


void Matrix3D::display() const
{
    if (m_data3D.IsEmpty())
    {
        cout << "empty matrix" << endl;
        return;
    }

    cout << "------------------------" << endl;
    const int rows = this->rows();
    const int cols = this->cols();
    const int Depths = this->Depths();
    cout << rows << "x" << cols << "x" << Depths << endl;
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        { 
            for(int k = 0 ;k < Depths; k++)
            {
                    cout << m_data3D[i][j][k] << ' '; /*This section will pose an error "E0142"*/
            }
            cout << endl;
         }
        
    }
}

我猜你的老師 class 是Array2D並且你主要只是將m_nDepths添加到它以將它變成Array3D 如果這個假設不正確,那么我在這里的回答很可能是完全錯誤的。

但如果我是對的,那么他的operator[]看起來像:

T* operator[](size_t r)
{
    assert(r >= 0 && r < m_nRows);
    return &(*(m_v.begin() + (r * m_nCols)));
}

這意味着當您執行m_data2D[i][j]時,第一個[i]應用於Array2D 如上所示,這將返回一個指針(在您的情況下可能是float* )。 然后將[j]應用於此指針,這會產生一些指針算術,從而產生float (對於float *xx[y]表示*(x+y) )。

換句話說,你的老師將他的二維數組逐行存儲在一維數組中,當你[]進入它時,你會得到一個指向正確行的指針,然后你可以進一步[]進入。

這一切都很好。

問題是當你向它添加第三個維度並嘗試相同的方法時:第一個[]仍然返回一個float* (但這次是正確的二維矩陣),第二個[]返回一個float (二維矩陣的正確行),第三個[]嘗試應用於float - 它不能,你會得到錯誤。

有兩種方法可以解決此問題:

  • 更改Array3D::operator[]的返回類型以返回某種二維數組類型,其operator[]的工作方式與原始Array2D
  • 放棄operator[]方法並將其替換為采用 3 arguments 的成員 function 並立即返回正確的元素。 我想這是我自己更喜歡的。

對於第二個選項,類似於(未測試,我很有可能弄亂了參數的順序):

T element(size_t x, size_t y, size_t z) const
{
    assert(x >= 0 && x < m_nDepths);
    assert(y >= 0 && y < m_nCols);
    assert(z >= 0 && z < m_nRows);
    return *(m_v.begin() + (x * m_nCols * m_nDepths +
                            y * m_nCols +
                            z));
}

T& element(size_t x, size_t y, size_t z)
{
    assert(x >= 0 && x < m_nDepths);
    assert(y >= 0 && y < m_nCols);
    assert(z >= 0 && z < m_nRows);
    return *(m_v.begin() + (x * m_nCols * m_nDepths +
                            y * m_nCols +
                            z));
}

結果cout << m_data3D[i][j][k] << ' '; 進入cout << m_data3D.element(i,j,k) << ' ';

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM