问题描述
|
我有一个包装函数(模板化))0ѭ,核心功能functionality1ѭ。
namespace N
{
A* Inner (void *p,int value,const int ID);
template<typename T>
A* Outer (T *p,const int ID) // ID is a compile time constant
{
return Inner (p,p->value,ID);
}
}
用法:
A *px = Outer(new X(3),12345);
A *py = Outer(new Y(4),987);
我设法通过一个编译时常量作为ID。因此,我正在考虑将“ 0”原型更改为
template<int ID,typename T>
A* Outer (T *p)
{
return Inner (p,ID);
}
用作
A *pz = Outer<333>(new Z(5));
想知道,新方法是否会对代码/性能级别产生影响?会对内联产生任何影响吗?
编辑:ID肯定是在编译时出现的,并且出现了多个“ 0”的实例(这就是为什么也要了解“ 8”的原因)。
解决方法
没有。该函数是模板,因此必须内联,并且像这样的常量折叠是内联函数时最常见的优化之一。这表明,如果您使用的是现代编译器,则绝对没有任何区别。
,首先,由于ID应该是
int
,因此模板应为
template<int ID,typename T>
A* Outer (T *p)
...
继续前进,尽管跌宕起伏,这取决于您的使用情况,但是这里有一些确定的事实:
性能
确实应该没有任何明显的区别。由于将为每个ID
值创建一个新函数,因此它的执行就像您刚刚使用局部ID
常量声明了自己的单独函数一样。因此,模板版本可能会更快,因为在函数调用时不会发生值的复制,但是就像我说的那样,它可能不足以构成破坏交易。
用法
这两种形式实际上并不等效。由于函数定义是在编译时根据ID
的值定义的,因此只能使用编译时常量(这似乎是您所期望的)。在原始版本中,用户可以写
int i = 10;
Outer<Z>(new Z(5),i);
尽管i
是一个变量,但会将其作为常量值复制到ID
中。
在模板版本中,他们不能写
int i = 10;
Outer<i,Z>(new Z(5));
由于编译器会为每个ID
值生成一个不同的函数,因此,当直到运行时才知道该值时,它不可能在编译时创建函数
因此,您的原始版本要灵活得多,而您建议的更改却非常严格。我认为大多数人都想以原始方式使用该函数,而不必强迫他们使用编译时常量。因此,我会坚持使用原始格式,除非出于某种原因您确实需要the11ѭ值作为编译时常量。
编译代码
对于已编译的代码,您的二进制文件会更大(假设您对ѭ11different的至少两个不同值使用该函数)。这是因为为程序中使用的ID的每个不同值创建了一个新函数。因此,如果您期望使用许多不同的值,则二进制文件中的膨胀可能会成为问题
内联
我没有明确的答案。我猜想如果内联受到影响,它可能会受到参数T
而不是ID
的影响。
,假设您正确执行了此操作(代码具有相同的功能),那么引入的唯一代价就是编译时间的增加,因为编译模板所花的时间比编译正常函数所需的时间更长。
您可以说“我有超级快的计算机,而编译需要1/2秒”,但是对于大型项目而言,这很重要。
,这将取决于您的编译器以及如何使用这些函数。
实际上,如果您已经进行了优化,那么唯一的
我想您会发现区别在于调用语法。但是如果
您遇到性能问题,配置文件,然后查看问题所在
来自(哪里。