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