簡體   English   中英

單指針和雙指針數組之間的區別

[英]Difference between single-pointer and double-pointer arrays

下面的代碼顯示動態分配的數組的地址。 當新行開始時,打印的地址會稍有不同。 如果我使用靜態數組,則地址完全相同,並且數組元素將一個接一個地移動。 什么原因?

void func(int* a, int** b)
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            cout << &a[i * n + j]<< " " << &b[i][j]<< endl;
        }
        cout << endl;
    }
}

int main()
{
    int** a;
    a = new int*[n];
    for (int i = 0; i < n; i++)
    {
        a[i] = new int[n];
    }
    func(a[0], a);

這就是您創建矩陣的方式。 沒有理由假定a[0] + 1 * n + j等於a[1] + j a[0]a[1]獨立分配。

這是一次獲取整個矩陣的方法。

int** a = new int*[n]; // allocate the row indexes
a[0] = new int[n * n]; // allocate the entire matrix
for (int i = 1; i < n; i++)
{
    a[i] = a[0] + i * n; // assign the row indexes. NOTE: a[0] is already assigned.
}

使用此分配, a[0] + 1 * n + j等於a[1] + j


靜態數組隱式分配整個矩陣分配,這就是為什么您的代碼對其有效的原因。

單指針和雙指針數組之間的區別

您可以在代碼中看到區別:

int** a;         // a is a pointer of type int**
a = new int*[n]; // a points to an array of pointers of type int*

和:

for (int i = 0; i < n; i++)
{
    a[i] = new int[n]; // a[i] points to an array of ints

你有它。

當新行開始時,打印的地址會稍有不同。 如果我使用靜態數組,則地址完全相同,並且數組元素將一個接一個地移動。

大概是在談論靜態數組數組,並將其與您擁有的指針數組進行比較。

數組的元素在內存中連續分配。 對於靜態數組數組,外部數組的元素是靜態數組,它們連續存儲在內存中。 對於指針數組,外部數組的元素是指針,它們也連續存儲在內存中。 另一方面,您動態分配的int數組不存儲在外部數組中。 它們的存儲位置是實現定義的,通常與保存指針的數組的位置無關。

也:

cout << &a[i * n + j]<< " " << &b[i][j]<< endl;

在這里,您正在訪問參數a所指向的數組的邊界之外,參數a所指向的數組在maina[0]指向,並且長度為n ,當i為非零值時,該長度小於i * n + j 結果是技術上未定義的行為,並且打印的地址絕對不是您分配的數組元素的絕對值。

Code below prints addresses of dynamically allocated array. 
Printed addresses become slightly different, when new line starts. If
I use static array, addresses are exactly the same, and array elements
are going one after another. What's the reason?

原因是以下調用將在每次調用時生成一個新地址,並且不能保證該地址是連續的。 a [i] = new int [n];

而,

整數a [10] [20]

這是一個靜態數組,將具有連續的內存分配。

在矩陣建模中,您使用了兩種相互矛盾的實現方式:在main ,您使用的是數組數組,每一行都位於單獨的內存中; func ,假設rows * columns元素的平面數組單一,將兩個索引映射為一個。 您必須選擇一個。

當然,在C ++中,您將編寫一個Matrix類來封裝此選擇。 例如,如果您想要單個平面數組(通常更可取),則可以編寫以下內容:

class Matrix
{
    int myRowCount;
    int myColumnCount;
    std::vector<int> myData;
public:
    Matrix( int rows, int columns )
        : myRowCount( rows )
        , myColumnCount( columns )
        , myData( rows * columns )
    {
    }

    int& operator()( int row, int column )
    {
        assert( row >= 0 && row < myRowCount
                && column >= 0 && column < myColumnCount );
        return myData[row * myColumnCount + column];
    }

    int const& operator()( int row, int column ) const
    {
        assert( row >= 0 && row < myRowCount
                && column >= 0 && column < myColumnCount );
        return myData[row * myColumnCount + column];
    }
};

您會注意到,我使用了std::vector而不是自己進行任何動態分配。 在這種情況下,差異並不大,但是在實踐中,除了非常例外的情況外,沒有經驗的C ++程序員會使用new數組。 有時有人想知道為什么它甚至在語言中也是如此。

您還將注意到,我已經重載了()運算符以進行索引。 您不能為[]提供兩個索引,這是該問題的解決方案之一。 另外, operator[]將采用單個索引,並返回一個代理對象,該對象也將采用單個索引。 雖然這是我更喜歡的解決方案,但它更加復雜。

暫無
暫無

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

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