模板非类型参数和分配数组内存

时间:2014-06-29 02:07:56

标签: c++ templates multidimensional-array non-type

我正在阅读的一本书中有一个示例课,用于解释概念:

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

从书中可以看出:

  

在Grid模板类中,您可以使用非类型模板参数来指定网格的高度和宽度,而不是在构造函数中指定它们。在模板列表而不是构造函数中指定非类型参数的主要优点是在编译代码之前已知值。回想一下,编译器通过在编译之前替换模板参数来生成模板化方法的代码。 因此,您可以在实现中使用普通的二维数组,而不是动态分配

对于动态内存分配,我不会对这种方法感到兴奋。首先这是否意味着多维数组将在堆栈上(因为它们似乎表明它不会被动态分配)?我不明白你为什么不想在堆上动态分配内存?

其次,是否有一些C ++规则(我忘记了)禁止在堆栈上声明多维数组,因此这种方法令人兴奋?

我试图了解在他们的示例中使用非类型模板参数的优点是什么。

3 个答案:

答案 0 :(得分:2)

  

首先这是否意味着多维数组将在堆栈上(因为它们似乎表明它不会被动态分配)?

正如您所看到的,您的数组直接是一个成员,它不是指针所指向的。

T mCells[WIDTH][HEIGHT];

但是说它在堆栈或堆上是不正确的,因为实际上数组是对象的一部分,它取决于对象的分配位置和方式。如果对象是在堆上分配的,那么它的数组子对象也是如此,如果整个对象在堆栈上,那么数组也是如此。

  

我不明白你为什么不想在堆上动态分配内存?

你可以。但是拥有一个新的数组既慢又容易出错(即它应该被删除等)。

  

其次,是否有一些C ++规则(我忘记了)禁止在堆栈上声明多维数组,因此这种方法令人兴奋?

没有。但任何数组的大小必须是编译时常量。非类型模板参数就是 - 编译时常量。如果它们只是int类型的函数参数,编译器就不会知道它们的值,在堆栈上创建一个数组(多维或其他)是违法的。

答案 1 :(得分:1)

不参考您提供的特定样本和来源:

  

对于动态内存分配这种方法,我并不感到兴奋

因为根本不需要更多的动态分配,即使您在堆栈上创建实例也是如此。

  

我不明白你为什么不想在堆上动态分配内存?

我经常在小型嵌入式系统上工作,有时我甚至没有动态内存管理的可能性(或者我不想承担开销)。对于这样的系统,以及您事先非常了解的,您可以/希望实际拥有的大小,这是一个非常好的配置抽象,您希望用于特定于目标的平台实现。

除了上述原因之外,动态分配还会在运行时引入性能损失,这对性能关键应用程序(例如游戏框架渲染引擎)来说是不可取的。

简而言之:
如果您有任何可以在编译时配置的东西,那么在运行时优先于配置。

答案 2 :(得分:1)

“首先,这意味着多维数组将在堆栈上”

如果Gameboard位于堆栈上(即它是一个局部变量),那么是,该数组也在堆栈上。

“我不明白你为什么不想在堆上动态分配内存?”

速度快。在这种情况下,由于Gameboard可能会长时间停留,所以没有必要。实际上,std::vector<std::vector<GamePiece>> mCells会比手动数组更好。

“是否有一些C ++规则(我忘记了)禁止在堆栈上声明多维数组”

不,这是允许的。但是与普通数组一样,维度必须在编译时才知道。

“我试图了解在他们的示例中使用非类型模板参数的优势。”

这是一个人为的例子。

考虑您要创建任意精度的整数类。精度越高,所需空间越大。可以经常创建和销毁此类,就像常规整数变量一样。如果动态分配数据,则速度较慢。通过使用模板参数指定所需的精度,可以将所需大小的常规数组创建为类的成员。每当将类放在堆栈上时,数组也会如此,这样会更快。