2013-03-14 60 views
0

我正在閱讀一本關於Safe C++的書。這裏的作者提到如何避免出現數組讀取的問題。這裏提到了我們如何避免多維數組的數組讀取問題。這裏的作者使用了operator()函數,如下面的鏈接所示,而不是operator [],並給出了下面的解釋。這裏多維數組超出範圍檢查

https://github.com/vladimir-kushnir/SafeCPlusPlus/blob/master/scpp_matrix.hpp

注意要訪問多維數組,我們要麼需要使用多個[]運營商,如矩陣[i] [j],或單()運算符,如基質(I,J )。

如果我們讓[]運算符返回一個指向第i行第零元素的T *指針,則可以實現第一種方法。但是,這否定了列索引超出範圍的診斷,這違背了在運行時捕獲錯誤的目的。當然,我們可以創建一些模板類,這會增加對行的智能引用,返回使用第一個運算符([i])的實例,然後使用第二個運算符(j)中的邊界檢查)。

我的問題是什麼筆者通過「意味着創造一些模板類,它會incldue智能引用到行,返回使用第一運營實例([1]),然後使用邊界檢查第二運算符(j))「。?請求提供示例代碼,瞭解如何在C++中實現上述邏輯?

感謝您的時間和幫助。

+2

您能不能通過您的努力啓發我們 – 2013-03-14 05:31:11

+0

當問題是「這意味着什麼」時,到目前爲止還有什麼努力? – FoolishSeth 2013-03-14 05:32:43

+1

作者意味着你返回一個包含嵌入引用的對象,該嵌入引用指向索引行的開始,並且在該對象內的大小限制,以便覆蓋'operator []'的邊界(對象)可以邊界檢查索引該維度類似於第一個維度被編入索引。 – WhozCraig 2013-03-14 05:36:33

回答

3

的基本思路看起來是這樣的:

#include <vector> 
#include <iostream> 

template <class T> 
class matrix { 
    size_t cols; 
    size_t rows; 
    std::vector<T> data; 

    class row_proxy { // This class is the part the question really asked about 
     size_t row; 
     matrix &m; 
    public: 
     row_proxy(matrix &m, size_t row) : row(row), m(m) {} 

     T &operator[](size_t col) { 
      if (row > m.rows || col > m.cols) 
       throw std::logic_error("Bad index"); 
      return m.data[row * m.cols + col]; 
     } 
    }; 

public: 

    matrix(size_t cols, size_t rows) : rows(rows), cols(cols), data(rows*cols) {} 

    row_proxy operator[](size_t row) { 
     return row_proxy(*this, row); 
    } 
}; 

int main() { 
    matrix<int> m(3, 3); 

    for (int i=0; i<3; i++) // fill the matrix with identifiable numbers 
     for (int j=0; j<3; j++) 
      m[i][j] = i * 100 + j; 

    for (int i=0; i<3; i++) { // show the content 
     for (int j=0; j<3; j++) 
      std::cout << m[i][j] << "\t"; 
     std::cout << "\n"; 
    } 

    try {      // test the bounds checking. 
     m[4][1] = 21; 
    } 
    catch(std::logic_error &e) { 
     std::cerr << e.what(); 
    } 

    return 0; 
} 

所以,當我們創建了一個矩陣,我們保存它的大小在rowscols。當我們在矩陣上使用operator[]時,它不會嘗試直接返回對矩陣中某個項的引用 - 而是返回一個代理類的實例,用於跟蹤行和矩陣,提供自己的operator[]

因此,當您使用matrix[a][b]時,第一個將amatrix保存到代理對象中。然後在該代理對象上調用[b]部分。這將檢查ab是否在我們爲矩陣保存的範圍內,如果是,則返回對矢量中正確對象的引用。否則,它會拋出一個std::Logic_error(可能不是最好的選擇 - 只是第一次發生在我身上)。

我應該補充說,這個總體思路有很多變化。僅舉一個例子,您可以在編譯時指定數組的大小,但將大小作爲模板參數傳遞。這可以有一些優點 - 例如,matrix<int, 2, 3>matrix<int, 3, 2>是完全不同的類型,所以您不能意外地將一個指派給另一個。它也可能有一些缺點(最明顯的是,你需要需要來知道編譯時的大小,否則根本不會工作)。

+0

感謝您的詳細解釋。現在我明白了作者的意思。 – venkysmarty 2013-03-14 08:12:52