std :: optional <T>的开销?

Vin*_*ent 2 performance g++ overhead c++14 stdoptional

既然已经接受了std :: experimental :: optional(或者即将被接受),我想知道当以下运算符获取内部值时,开销产生的开销和后果是什么:

->
*
value
value_or
Run Code Online (Sandbox Code Playgroud)

与没有的情况相比std::optional.对于计算密集型程序来说,这可能尤为重要.

例如,与a std::vector<std::experimental::optional<double>>相比,操作上的开销是std::vector<double>多少?

Moo*_*uck 8

->并且*应该有零开销.
value并且value_or应该有一个分支的开销:if(active)
同样,复制/移动构造函数,复制/移动分配,交换,布设,operator==,operator<,和析构函数应该也有一个分支的开销.
然而,开销的一小部分是如此之小,甚至可能无法衡量.说真的,编写漂亮的代码,不要担心这里的性能.很可能使代码变得漂亮,导致它运行得比你试图快速运行更快.反直觉,但无论如何都要这样做.

肯定存在开销变得难以察觉的情况,例如对大量optionals 进行排序.在这些情况下,有四种情况,
(A)所有已知的选项都是提前空的,在这种情况下,为什么要排序?
(B)某些选项可能有效,也可能不有效,在这种情况下需要开销,没有更好的方法.
(C)已知所有选项都具有提前值,并且您不需要已排序的数据,在这种情况下,使用零开销运算符来复制使用原始类型的数据的副本而不是optional和排序.
(D)已知所有选项都具有提前值,但您需要就地排序数据.在这种情况下,optional添加不必要的开销,解决它的最简单方法是执行步骤C,然后使用无开销运算符来移数据.

  • *“然而,一堆开销是如此之小,甚至可能无法测量”* 嗯?在紧密循环中,它肯定会对性能产生影响。http://stackoverflow.com/q/11227809/420683 (6认同)

man*_*lio 8

除了另一个答案,您还应该考虑这std::optional需要额外的内存。

通常它不仅仅是一个额外的字节,而是(至少对于“小”类型)由于 padding 导致的2 倍空间开销。

也许 RAM 不是问题,但这也意味着缓存中可用的值更少。

哨兵值,如果特定知识允许使用它,可能是更好的选择(可能markable以保持类型安全的形式)。

一个有趣的阅读是:Boost 可选 - 性能考虑