【发布时间】:2012-03-27 08:31:13
【问题描述】:
【问题讨论】:
-
可能与参数转发效率低有关?
-
如果有人能概括出那些好和一些之间的区别可能会有所帮助。
-
@Cheers:我认为内联可以解决这个问题——但话又说回来,我不得不承认我已经遇到了直接决定停止内联的编译器超过 3 或 4 个。
【问题讨论】:
A non-recursive implementation 具有更好的编译时性能。信不信由你,在像std::tuple 这样的大量使用的库设施中,它的实现方式会影响(无论好坏)客户端看到的编译时间。递归实现往往会产生与递归深度呈线性关系的编译时间(甚至可能更糟)。
这不仅仅影响元组本身的实例化。 std::get<I>(tuple) 例如,一个实现需要线性数量的编译时间,另一个实现需要恒定数量的编译时间。在处理元组的元组时,这种影响可能会迅速恶化(或不会恶化)。 IE。递归实现可能会导致 O(N^2) 编译时间,而非递归实现仍然是 O(1)。
首先,libc++ 实现按客户端指定的顺序排列对象,但使用编译器的空基类优化工具优化空组件的空间。
【讨论】:
我不记得 Andrei Alexandrescu 的 GoingNative 2012 演讲确切,但他谈到了这一点,他提到的其中一个要点是内存布局。如果我有一个std::tuple<int, short, char, char>,它将在内存中以char, short, int 的形式存在,并且此布局将比以int, short, char 布局时多占用(在我的系统上)4 个字节。 R. Martinho Fernandes 提醒我,最好的 方法是以最小化填充的顺序在内存中排序它们,这既不是给定的顺序 也不是 反向顺序。 (Naïve 继承的顺序是相反的)。
如果我写std::tuple<int, char, short, char>,一个通过朴素继承工作的元组会将它们按char, short, int 的顺序放入内存中,使用 3 个字节的填充,当最优具有零字节的填充时。 (int, short, char, char 或 char, char, short, int)。
假设我是对的,它是关于填充的,那么 R. Martinho Fernandes said “[我的论点] 并不排除以最佳顺序在实际实现中使用递归继承。”,这就是为什么我指定 naïve 继承是不好的。
(内存中的顺序确实不意味着get<0> 将给出不同的对象,并且 R. Martinho Fernandes 正确地指出该顺序应该对用户不可见。但是,这些是我从 GoingNative 事件中得到了提醒。)
视频位于http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/Variadic-Templates-are-Funadic,幻灯片位于http://ecn.channel9.msdn.com/events/GoingNative12/GN12VariadicTemplatesAreFunadic.pdf。
【讨论】:
get<> 调用,但是所有的 static_asserts 都通过了,并且它在 libc++ 的 clang 上运行良好。我不知道如何进行编译时性能分析,所以这可能是低效的。如果您有任何问题,请在聊天中联系我 :)
不使用基类链的一个原因是不涉及构造函数链:参数直接转发给适当的子对象。此外,似乎非递归实现对编译器的压力要小得多,并且创建的 [内部] 符号也少得多。更不用说实际上不是基类链更容易。
【讨论】: