现在std::experimental::optional已被接受(或即将被接受),我想知道当以下运算符获取内部值时生成的程序集的开销和后果是什么:
->
*
value
value_or
与没有的情况相比std::optional
。它对于计算密集型程序可能特别重要。
例如,与 astd::vector<std::experimental::optional<double>>
相比,a上的操作开销的数量级是std::vector<double>
多少?
现在std::experimental::optional已被接受(或即将被接受),我想知道当以下运算符获取内部值时生成的程序集的开销和后果是什么:
->
*
value
value_or
与没有的情况相比std::optional
。它对于计算密集型程序可能特别重要。
例如,与 astd::vector<std::experimental::optional<double>>
相比,a上的操作开销的数量级是std::vector<double>
多少?
->
并且*
应该有零开销。
value
并且value_or
应该有一个分支的开销:if(active)
另外,复制/移动构造函数、复制/移动赋值、swap、emplace、 ... operator==
、operator<
析构函数也应该有一个分支的开销。
然而,一组开销是如此之小,以至于可能甚至无法测量。说真的,写漂亮的代码,不要担心这里的性能。使代码漂亮的可能性会导致它运行得比你试图让它更快的速度更快。违反直觉,但无论如何都要这样做。
肯定存在开销变得明显的情况,例如对大量optional
s 进行排序。在这些情况下,有四种情况,
(A)所有已知的选项都提前为空,在这种情况下,为什么要排序?
(B) 一些选项可能会或可能不会被激活,在这种情况下需要开销并且没有更好的方法。
(C) 所有选项都提前知道有值,并且您不需要排序数据,在这种情况下,使用零开销运算符制作副本使用原始类型的数据而不是, 并对它optional
进行排序。
(D) 已知所有选项都提前具有值,但您需要就地排序数据。在这种情况下,optional
增加了不必要的开销,最简单的解决方法是执行步骤 C,然后使用无开销运算符将数据移回。
除了其他答案之外,您还应该考虑这std::optional
需要额外的内存。
通常它不仅仅是一个额外的字节,而是(至少对于“小”类型)由于 padding 导致的2 倍空间开销。
也许 RAM 不是问题,但这也意味着缓存中可用的值更少。
如果特定知识允许使用哨兵值,它可能是更好的选择(可能markable
以保持类型安全的形式)。