2013-07-15 83 views
0

當大量問題出現時,我正在使用非類型參數(避免動態分配數組)的模板函數。我的第一個問題涉及編譯時變量賦值。這從以下的嘗試出現在調用模板函數: 在C++中編譯vs vs運行時const變量賦值和vlas的分配

template<int n> 
int *getDegrees(int A[][n]) { 
    //return degrees 
} 

int main(int argc, char **argv) { 
    int n = 10; 
    int A[n][n]; 
    int *degs = getDegrees<n>(A); 
} 

在這裏,我們有兩個錯誤:第一,編譯器無法解析調用getDegrees(A)

main.cc:27: error: no matching function for call to ‘getDegrees(int [(((long unsigned int)(((long int)n) + -0x00000000000000001)) + 1)][(((long unsigned int)(((long int)n) + -0x00000000000000001)) + 1)])’ 

其次,我們無法在模板調用中使用n,因爲它不是一個常量表達式。簡單地使n不變並解決問題

const int n = 10; 

但是,如果我是做

int m = 10; 
const int n = m; 

我們得到了同樣的錯誤。雖然編譯器可以允許第二項任務,但是認爲它是不好的形式嗎?另外,爲什麼要使n在解決函數調用中有所不同?

我的其他問題關於vlas:在堆棧或堆上爲它們分配的內存(這是依賴於編譯器的)?即使允許他們使用C++,似乎也存在一些爭議,應該避免使用向量(或類似的容器)嗎?

感謝任何見解!

+2

VLA不是C++。你想C答案? –

+0

有趣的是,我的GNU C++編譯器與vlas沒有問題,我不知道它們是C構造。 C答案會很好,謝謝你的提醒! – glinka

+0

如果你想動態堆棧分配,你總是可以嘗試alloca()。 –

回答

5

我會盡力回答你的問題。
可以改變函數原型通過參考接收陣列:

template<size_t n> // see the type 
int *getDegrees(int (&A)[n][n]) { // see the signature 
    // ... 
} 

在上述代碼中,我們正在利用該陣列具有相同的尺寸的事實。
然而,在一般情況下,它應該是:

template<size_t n1, size_t n2> // see the type 
int *getDegrees(int (&A)[n1][n2]) { // see the signature 
    // ... 
} 

如果尺寸太大則錯誤是由編譯器發出通知你。例如(來自克++):

error: size of array ‘A’ is too large

現在來到另一個問題關於恆定整數的分配之間的差。
在C++中,陣列尺寸必須編譯時間常數和

const int n = 10; 

滿足這一要求。由於編譯器可以證明這一點,因此10是一個文字編號,分配給n

在情況下,

int m = 10; 
const int n = m; 

編譯器發現該的n源是一個編譯時間常數本身。因此它使代碼不正確。

+0

雖然格式不正確,但n表現出預期的行爲(它被賦予不可更改的值10)。這樣的結構是否應該避免? – glinka

+1

@glinka:G ++有一個不合格的擴展,允許VLA(數組whos bounds不是編譯時間常量),但即使G ++也要求模板參數是編譯時間常量。我會避免他們。 –