C++ 用模板重写的类会使程序变慢(在运行时)
我有一个串行内存2D数组的类,它最初是C++ 用模板重写的类会使程序变慢(在运行时),c++,performance,templates,runtime,C++,Performance,Templates,Runtime,我有一个串行内存2D数组的类,它最初是ints的数组。现在我需要一个具有另一种类型的类似数组,我已经用模板重写了这个类;唯一的区别在于存储对象的类型: template <class T> class Serial2DArray { ... T ** Content; } 下面是实际的类模板: #include <malloc.h> template <class T> class Serial2DArray { public:
int
s的数组。现在我需要一个具有另一种类型的类似数组,我已经用模板重写了这个类;唯一的区别在于存储对象的类型:
template <class T>
class Serial2DArray
{
...
T ** Content;
}
下面是实际的类模板:
#include <malloc.h>
template <class T>
class Serial2DArray
{
public:
Serial2DArray()
{
Content = NULL;
Width = 0;
Height = 0;
}
Serial2DArray(int _Width, int _Height)
{
Initialize(_Width, _Height);
}
~Serial2DArray()
{
Deinitialize();
}
T ** Content;
int GetWidth()
{
return Width;
}
int GetHeight()
{
return Height;
}
int Initialize(int _Width, int _Height)
{
// creating pointers to the beginning of each line
if((Content = (T **)malloc(_Height * sizeof(T *))) != NULL)
{
// allocating a single memory chunk for the whole array
if((Content[0] = (T *)malloc(_Width * _Height * sizeof(T))) != NULL)
{
// setting up line pointers' values
T * LineAddress = Content[0];
for(int i=0; i<_Height; ++i)
{
Content[i] = LineAddress; // faster than Content[i] =
LineAddress += _Width; // Content[0] + i * _Width;
}
// everything went ok, setting Width and Height values now
Width = _Width;
Height = _Height;
// success
return 1;
}
else
{
// insufficient memory available
// need to delete line pointers
free(Content);
return 0;
}
}
else
{
// insufficient memory available
return 0;
}
}
int Resize(int _Width, int _Height)
{
// deallocating previous array
Deinitialize();
// initializing a new one
return Initialize(_Width, _Height);
}
int Deinitialize()
{
// deleting the actual memory chunk of the array
free(Content[0]);
// deleting pointers to each line
free(Content);
// success
return 1;
}
private:
int Width;
int Height;
};
- 1016832字节
Serial2DArray<int> TestArray;
Serial2DArray<int> ZeroArray;
Serial2DArray TestArray; // NOT-template class with ints
Serial2DArray ZeroArray; // methods are in class declaration
Serial2DArray<int> TestArray;
Serial2DArray<int> ZeroArray;
Serial2DArray<double> AnotherArray;
Serial2DArray<double> YetAnotherArray;
Serial2DArray测试阵列;
Serial2DArray零数组;
串行2个数组和另一个数组;
Serial2DArray-YetAnotherArray;
- 1017344字节
以下是关于该主题的维基百科文章:。当强制编译器内联程序中的每个函数和方法时,问题可能是相同的,只要编译器可以使用它。该标准试图通过将
内联
关键字设置为“请求”来防止这种情况,编译器不能每次都遵循该关键字。例如,GCC以中间语言生成代码,以评估生成的二进制文件是否不会导致代码膨胀,并可能因此放弃内联请求。这是我为测试这个特定类而构建的一个小程序,它只有一个此类对象和两个将元素转换为0的不同函数,还没有修改。这种1-2%的减速在不同的机器和许多后续测试中是一致的。您是否对这两个版本进行了优化编译?是的,并且两个版本的设置都相同。@fynjzn:问题不是这样的。这两个版本可能都是在调试模式下编译的。@ildjarn我理解;两者都处于发布模式。已知的非问题,更像。首先,编译器可以使用相同的汇编程序折叠模板实例。第二,如果你随机跳转,更多的代码只意味着更多的页面错误。但如果最近是这样的话,这种情况已经很久没有出现了。看看布鲁斯·埃克尔的书《用c++思考》。他在书中谈到了这个问题,这可能相当棘手。关于第二点,你是绝对正确的。但这样的话,OP就可以在他的计划中走上这条特殊的道路了。不幸的是,从统计上来说还行。@yves:第一点,至少7年了——不完全是最近的。@yves:讽刺的是,因为你是传播关于代码膨胀的错误信息的人。关于你提供链接的帖子的答案,在我看来都是错误的。注意…的错误感觉。。C++模板给你的性能。以及内联代码中的所有内容。这是一个错误的普遍观点。。。花些时间阅读Bruce Eckel的书“用C++思考”第1或第2卷(不记得在哪一卷中处理了模板代码膨胀的主题),并阅读他处理这个问题的方法。非常有趣。(最初是作为对你答案的评论发布的,你说真正的问题来自将所有代码放在一个标题中)这是什么编译器?似乎这只会给编译器更多的信息(并且不会强迫任何悲观的说法,比如总是内联)。@yvesBaumes好吧,我发布了一个额外的信息作为答案(并且被删除了)——在类声明中包含方法的非模板类也很慢,虽然不是在单独的.cpp中使用方法的模板类(以及类声明中的.h中的头),但速度很快。否则,这两个版本是相同的(只是将实际的方法从类声明移动到类声明)。因此,我开始认为这可能根本不是模板的问题?@fynjzn关于类内声明的慢非模板类,从我的观点来看,原因可能是:编译器将类内声明的方法视为开发人员的内联请求。只要考虑一下访问器,比如通常的getter和setter,就不需要使用inline关键字来请求内联。然后它会加入代码膨胀的问题,但这也意味着你的编译器确实遵循了请求,而它一定没有遵循它(…)等等,如果它是2.9 vs.2.8或29 vs.28,并且是完全可持续的,那么为什么最初的问题会说“我注意到现在它的工作速度慢了1-2%?”?如果你有足够宽的误差条,可以把3.5%的误差称为1-2%,那么这个测量就没有多大用处了。
Serial2DArray<int> TestArray;
Serial2DArray<int> ZeroArray;
Serial2DArray<double> AnotherArray;
Serial2DArray<double> YetAnotherArray;