我有一个与此类似的容器。
template <typename Nat, typename Elt>
class NatMap {
public:
Elt& operator[] (Nat nat) {
return tab [nat.GetRaw()];
}
private:
Elt tab [Nat::kBound];
};
我想删除Elt有一个默认构造函数的要求:
template <typename Nat, typename Elt>
class NatMap {
public:
Elt& operator[] (Nat nat) {
return ((Elt*)tab) [nat.GetRaw()];
}
private:
char tab [Nat::kBound * sizeof(Elt)];
};
我使用g ++ - 4.3并且这个代码在我的应用程序中比前一代码慢25%。不幸的是,减速并未体现在综合基准测试中。 我想这是关于编译器优化,别名,对齐或类似的东西。
我该怎样做才能恢复表现? (虽然不需要默认的构造函数)
更新
刚才我尝试了新的g ++ - 4.4,它为后面的代码提供了以下警告:
dereferencing pointer '<anonymous>' does break strict-aliasing rules
答案 0 :(得分:1)
您可能遇到对齐问题。如果Elt是原始对齐类型以外的某种大小,那么通过放置到字符数组中将其分配可能涉及许多未对齐的读取,当编译器为您对齐时,您不会看到这些读取。或者您可能遇到一个称为加载命中存储的问题,某些处理器在将值写入内存然后立即将其读回时会显示;在那些处理器中,只要是管道,它就可以是一个停顿。
或者它可能完全不同,GCC会产生某种病理代码。
不幸的是,堆栈跟踪无法帮助追踪这些问题,因为它们看起来像加载操作(lw
,lb
等),需要40个周期而不是1个周期。停顿在CPU内部的微代码中,而不是您编写的x86代码。但是使用-S
命令行选项查看程序集可以帮助您弄清楚编译器实际发出的内容,以及它们在两个实现之间的区别。也许在一个版本中出现了一些糟糕的操作。
答案 1 :(得分:0)
小建议:不要试图做出有根据的猜测,比如编译器优化是不同的,你可以单步执行,也可以找出with this unorthodox method。