2014-06-29 34 views
3

有一本書的示例類我讀始終用來解釋概念:模板非類型參數和分配陣列存儲

class Gameboard{ 
public: 
    Gameboard(int inWidth, int inHeight); 
    Gameboard(const Spreadsheet& src); 
    Gameboard& operator=(const Spreadsheet& rhs); 

private: 
    GamePiece** mCells; 
    size_t width; 
    size_t height; 
}; 

他們再介紹模板和引入更新的類:

template<typename T> 
class Grid{ 
public: 
    Grid<T>(int inWidth, int inHeight); 
    Grid<T>(const T& src); 
    Grid<T>& operator=(const T& rhs); 

private: 
    T** mCells; 
    size_t width; 
    size_t height; 
}; 

最後他們引入非類型模板參數,說你現在可以這樣做:

template<typename T, size_t WIDTH, size_t HEIGHT> 
class Grid{ 
public: 
    Grid<T>(); 
    Grid<T>(const T& src); 
    Grid<T>& operator=(const T& rhs); 

private: 
    T mCells[WIDTH][HEIGHT]; 
}; 

從書:

在網格模板類,你可以使用非類型模板參數指定網格的高度和寬度,而不是在構造函數中指定它們。在模板列表中指定非類型參數而不是構造函數的主要優點是,在編譯代碼之前,這些值是已知的。回想一下,在編譯之前,編譯器通過替換模板參數來爲模板化方法生成代碼。 因此,您可以在您的實施中使用普通的二維數組,而不是動態分配它

我不明白這種動態內存分配方法的興奮。首先,這是否意味着多維數組將會在棧上(因爲它們似乎暗示它不會被動態分配)?我不明白爲什麼你不想動態分配堆上的內存?其次,是否存在一些C++規則(我忘記了),它禁止在棧上聲明多維數組,因此這種方法的興奮?

我想了解在他們的例子中使用非類型模板參數的優點是什麼。

+0

把它看作是說明性的,不斷學習,看看其他信息來源。我不能僅僅通過這個例子來判斷這本書,所以對我來說這不是很有說服力,有許多設計決策可以讓你使用這種類型的環境,['std :: array'](http:///en.cppreference.com/w/cpp/container/array),例如,在相同的路線中提供替代['std :: vector'](http://en.cppreference.com/w/cpp/容器/載體)。 –

回答

2

首先,這是否意味着多維數組將會在堆棧上(因爲它們似乎表明它不會被動態分配)?你可以看到,你的數組直接是一個成員,它不是由一個指針間接指定的。

T mCells[WIDTH][HEIGHT]; 

但它不會是正確地說,它是在堆棧或堆上因爲事實上數組是你的目標的一部分,它是依賴於在何處以及如何你的對象分配。如果對象被分配到堆上,那麼它的數組子對象也將會是,如果整個對象在堆棧上,數組也是如此。

我不明白你爲什麼不想動態分配堆上的內存?

你可以。但是擁有new'd數組的速度更慢且更容易出錯(即它應該被刪除等)。其次,是否存在一些C++規則(我忘記了),它禁止在棧上聲明多維數組,因此這種方法的興奮?

不,但任何數組的大小必須是編譯時常量。非類型模板參數正是 - 編譯時間常量。如果它們只是int類型的函數參數,編譯器就不會知道它們的值,並且在堆棧上創建一個數組(多維或其他)將是非法的。

+0

_'但是任何數組的大小必須是一個編譯時常量'_至少GCC有擴展(用於本地堆棧分配數組),應該克服這個問題嗎? –

1

沒有提及具體的樣品和來源你給:

由於沒有更多的動態分配,需要我沒有得到所有關於動態內存分配

這種方法的興奮即使你在堆棧上創建實例,也是如此。

我不明白你爲什麼不想動態分配堆上的內存?

我經常在小型嵌入式系統上工作,在那裏我有時甚至沒有動態內存管理的可能性(或者我不想承擔開銷)。對於這樣的系統,以及事先非常熟悉的地方,您可以/想要的實際大小,這是您希望用於目標特定平臺實現的非常好的配置抽象。除了上述原因外,動態分配在運行時引入了性能關鍵應用程序(例如遊戲框架渲染引擎)所不希望的性能。

總而言之:
如果您在編譯時有任何可以確定配置的內容,那麼在運行時更喜歡這樣做。

1

「首先這是否意味着多維數組是在棧上」

如果Gameboard位於堆棧(即它是一個局部變量)然後是,數組也是在堆棧中。

「我不明白你爲什麼不想在堆上動態分配內存?」

速度。在這種情況下,由於Gameboard可能會長時間存在,因此沒有必要。實際上,std::vector<std::vector<GamePiece>> mCells會比手動陣列更好。

「有沒有以禁止在聲明堆棧上的多維數組一些C++規則(我差點忘)」

不,這是允許的。但是像正常的數組一樣,維數在編譯時必須知道。

「我想了解在他們的示例中使用非類型模板參數的優點。」

這是一個人爲的例子。

考慮你想創建一個任意精度的整數類。精度越高,需要的空間就越多。這個類可能會經常被創建和銷燬,就像常規的整型變量一樣。如果數據是動態分配的,則速度較慢。通過使用模板參數指定所需的精度,可以創建所需大小的常規數組作爲類的成員。無論何時將類放在堆棧上,數組也一樣,而且這會更快。