简体   繁体   中英

Template non-type parameters and allocating array memory

There is an example class in a book I am reading used throughout to explain concepts:

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;
};

they then introduce templates and introduce an updated class:

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;
};

finally they introduce non-type template parameters and say you can now do this:

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];
};

From the book:

In the Grid template class, you could use non-type template parameters to specify the height and width of the grid instead of specifying them in the constructor. The principle advantage to specifying non-type parameters in the template list instead of the constructor is that the values are known before the code is compiled. Recall that the compiler generates code for templatized methods by substituting in the template parameters before compiling. Thus you can use a normal two-dimensional array in your implementation instead of dynamically allocating it .

I don't get all the excitement with this approach regarding the dynamic memory allocation. Firstly does this mean the multidimensional array would be on the stack (because they seem to suggest it wouldnt be dynamically allocated)? I don't understand why you wouldn't want to dynamically allocate the memory on the heap?

Secondly, is there some C++ rule (which I am forgetting) which prohibits declaring a multidimensional array on the stack, hence the excitement with this approach?

I am trying to understand what is the advantage of using non-type template parameters in their example.

Firstly does this mean the multidimensional array would be on the stack (because they seem to suggest it wouldnt be dynamically allocated)?

As you can see, your array is directly a member, it's not indirected by a pointer.

T mCells[WIDTH][HEIGHT];

But it wouldn't be correct to say that it's on the stack or the heap since in fact the array is a part of your object and where it is depends on where and how your object is allocated. If the object is allocated on the heap, its array subobject will be too, if the whole object is on the stack, so will the array be.

I don't understand why you wouldn't want to dynamically allocate the memory on the heap?

You could. But having a new'd array is both slower and more error-prone (ie it should be deleted etc).

Secondly, is there some C++ rule (which I am forgetting) which prohibits declaring a multidimensional array on the stack, hence the excitement with this approach?

No. But the size of any array must be a compile-time constant. Non-type template parameters are exactly that - compile time constants. Had they been simply function parameters of an int type, the compiler would not know their value and it would be illegal to create an array (multidimensional or otherwise) on the stack.

Without referring to the particular samples and sources you give:

I don't get all the excitement with this approach regarding the dynamic memory allocation

Because no more dynamic allocation is needed for such at all, even if you're creating instances on the stack.

I don't understand why you wouldn't want to dynamically allocate the memory on the heap?

I'm often working on small embedded systems, where I sometimes don't even have the possibility for dynamic memory management (or I don't want to bear the overhead). For such systems, and where you very well know in advance, which sizes you can/want actually have, it's a pretty good configuration abstraction you want to use for target specific platform implementations.

Also besides the above reasons, dynamic allocation introduces a performance hit at runtime that is unwanted for performance critical applications (eg game framework rendering engines).

In short and general:
If you have anything that can be certainly configured at compile time, prefer this over configuring at run time.

"Firstly does this mean the multidimensional array would be on the stack"

If Gameboard is located on the stack (ie it's a local variable) then yes, the array is also on the stack.

"I don't understand why you wouldn't want to dynamically allocate the memory on the heap?"

For speed. In this case, as Gameboard will probably stick around for a long time, it's not necessary. Actually, std::vector<std::vector<GamePiece>> mCells would be better than manual arrays.

"is there some C++ rule (which I am forgetting) which prohibits declaring a multidimensional array on the stack"

No, it's permissible. But like normal arrays, the dimensions must be known at compile-time.

"I am trying to understand what is the advantage of using non-type template parameters in their example."

It is a contrived example.

Consider you want to create an arbitrary-precision integer class. The higher the precision, the more space is required. This class may be created and destroyed frequently, just like a regular integer variable. If the data is allocated dynamically, this is slower. By specifying the required precision with a template parameter, a regular array of the required size can be created as a member of the class. Whenever the class is placed on the stack, so will the array, and this will be faster.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM