2014-12-13 27 views
0

我已經注意到,在gcc C11中,您可以將任何矩陣傳遞給函數fn(int row, int col, int array[row][col])。如何翻譯我的下面放置(在一個鏈接到另一個stackoverflow答案)在C11程序到C++ 11程序?C++ 11中的二維矩陣是否與C11類似?

C - allocating a matrix in a function

正如你看到的,我可以傳遞給函數的靜態和動態分配的數組中的C11。在C++ 11中可能嗎?

我做了一個基於不同的計算器答案的示例程序,但所有函數都適用於array1,並且它們都不適用於array2,其中double array1[ROW][COL] = { { } }auto array2 = new double[ROW][COL]()

如何在C11 fn(int row, int col, int array[row][col])中製作兩個陣列的功能?

#include <iostream> 
#include <utility> 
#include <type_traits> 
#include <typeinfo> 
#include <cxxabi.h> 
using namespace std; 

const int ROW=2; 
const int COL=2; 

template <size_t row, size_t col> 
void process_2d_array_template(double (&array)[row][col]) 
{ 
    cout << __func__ << endl; 
    for (size_t i = 0; i < row; ++i) 
    { 
     cout << i << ": "; 
     for (size_t j = 0; j < col; ++j) 
      cout << array[i][j] << '\t'; 
     cout << endl; 
    } 
} 

void process_2d_array_pointer(double (*array)[ROW][COL]) 
{ 
    cout << __func__ << endl; 
    for (size_t i = 0; i < ROW; ++i) 
    { 
     cout << i << ": "; 
     for (size_t j = 0; j < COL; ++j) 
      cout << (*array)[i][j] << '\t'; 
     cout << endl; 
    } 
} 

// int array[][10] is just fancy notation for the same thing 
void process_2d_array(double (*array)[COL], size_t row) 
{ 
    cout << __func__ << endl; 
    for (size_t i = 0; i < row; ++i) 
    { 
     cout << i << ": "; 
     for (size_t j = 0; j < COL; ++j) 
      cout << array[i][j] << '\t'; 
     cout << endl; 
    } 
} 

// int *array[10] is just fancy notation for the same thing 
void process_pointer_2_pointer(double **array, size_t row, size_t col) 
{ 
    cout << __func__ << endl; 
    for (size_t i = 0; i < row; ++i) 
    { 
     cout << i << ": "; 
     for (size_t j = 0; j < col; ++j) 
      cout << array[i][j] << '\t'; 
     cout << endl; 
    } 
} 

int main() 
{ 
    double array1[ROW][COL] = { { } }; 
    process_2d_array_template(array1); 
    process_2d_array_pointer(&array1); // <-- notice the unusual usage of addressof (&) operator on an array 
    process_2d_array(array1, ROW); 
    // works since a's first dimension decays into a pointer thereby becoming int (*)[COL] 

    double *b[ROW]; // surrogate 
    for (size_t i = 0; i < ROW; ++i) 
    { 
     b[i] = array1[i]; 
    } 
    process_pointer_2_pointer(b, ROW, COL); 


    // allocate (with initialization by parentheses()) 
    auto array2 = new double[ROW][COL](); 

    // pollute the memory 
    array2[0][0] = 2; 
    array2[1][0] = 3; 
    array2[0][1] = 4; 
    array2[1][1] = 5; 

    // show the memory is initialized 
    for(int r = 0; r < ROW; r++) 
    { 
     for(int c = 0; c < COL; c++) 
      cout << array2[r][c] << " "; 
     cout << endl; 
    } 

    //process_2d_array_pointer(array2); 
    //process_pointer_2_pointer(array2,2,2); 

    int info; 
    cout << abi::__cxa_demangle(typeid(array1).name(),0,0,&info) << endl; 
    cout << abi::__cxa_demangle(typeid(array2).name(),0,0,&info) << endl; 

    return 0; 
} 
+0

爲什麼不只是傳遞像'vector >&'? – Michael 2014-12-13 09:12:11

+0

我知道這個模板解決方案。但如果我在我的程序中提到了這兩個數組,我想知道正確的答案。是否有可能將這兩個數組傳遞給相同的函數? – 42n4 2014-12-13 09:20:35

+0

@ 42n4 - 爲什麼你需要爲這樣一個看似簡單的問題發佈所有這些代碼? 5行main()函數調用幾個虛擬函數是否足以傳遞您的觀點? – PaulMcKenzie 2014-12-13 09:28:44

回答

2

您在C11中使用的功能是在C99中引入的,專門設計用於高效和輕鬆地處理多維數組。雖然C++在涉及(多維)數組時使用C語言共享基本語法,但在C++中數組類型的功能要低得多:在C++中,數組類型的大小需要是編譯時間常量。這裏有幾個例子:

void foo(int a, int b) { 
    int foo[2][3];  //legal C++, 2 and 3 are constant 
    int bar[a][3];  //Not C++, proposed for C++17: first dimension of an array may be variable 
    int baz[a][b];  //Not C++, legal in C99 

    int (*fooPtr)[2][3]; //legal C++ 
    int (*barPtr)[a][3]; //Not C++, legal in C99 
    int (*bazPtr)[a][b]; //Not C++, legal in C99 

    typedef int (*fooType)[2][3]; //legal C++ 
    typedef int (*barType)[a][3]; //Not C++, legal in C99 
    typedef int (*bazType)[a][b]; //Not C++, legal in C99 

    int (*dynamicFoo)[3] = new int[2][3]; //legal C++ 
    int (*dynamicBar)[3] = new int[a][3]; //legal C++ 
    int (*dynamicBar)[b] = new int[a][b]; //Not C++ 
} 

正如你看到的,幾乎一切與動態大小的數組C'S可能在C是不可能++。即使是爲下一個C++標準提出的VLA擴展也沒什麼幫助:它僅限於數組的第一維。

在C++中,您必須使用std::vector<>才能實現C99可變長度數組。與所有的後果:

  • 數據在std::vector<std::vector<> >不在內存中連續的。你的緩存可能不會這樣。

  • std::vector<std::vector<> >並不保證所有線陣列具有相同的長度。根據您的使用情況,這可能很有用,也可能很痛苦。

  • 如果您有一個迭代器到std::vector<std::vector<> >中的元素,則無法將其前進到下一行中的相應元素。

2

C++ does not have VLA。它被提議用於C++ 17,但是還有很多工作要做,因爲它對類型系統有很大的改變,並且使用C風格的數組在C++中是不受歡迎的。

正如您所發現的,您可以在編譯時知道大小時使用模板。如果在編譯時不知道大小,那麼最好的辦法是使用一個包裝在一個類中的單維vector以您希望訪問它的方式訪問它。

當然也可以使用vectorvectors;描述一個鋸齒狀的數組。無論你喜歡超過單個大內存塊取決於各種事情(編碼的複雜性,運行時速度/內存使用考慮等)。

+0

感謝這個C VLA stackoverflow鏈接! – 42n4 2014-12-13 10:34:18