预增量 vs post-增量 std::atomic<int>
pre-increment vs post-increment on std::atomic<int>
一般的经验法则是在不立即评估值的情况下(即您只想增加 object/iterator),更喜欢在 STL 迭代器上使用预增量。这是因为一般来说预自增的实现比post自增更高效。
但是 std::atomic 呢?如果我 运行 静态分析(使用 PVS studio),我会收到一条警告说预增量应该更有效,但是当我查看预增量的实现时(在 Visual Studio 2015)它看起来效率低于 post-increment?
是否有在 STL 原子值上使用预增量而不是 post 增量的一般规则,还是特定于实现?
效率(在这个级别)总是具体实现。
例如,作为经验法则"prefer pre-increment for STL iterators"的反例,事实证明在实践中很少有编译器会为预增量和post-增量生成不同的代码。 (post-增量的伪造副本被优化得一无是处。)
我现在无法访问 windows,但在 gcc 中,区别在于
__atomic_fetch_add(&_M_i, 1, memory_order_seq_cst);
和
__atomic_add_fetch(&_M_i, 1, memory_order_seq_cst);
它们是内置的,所以你可以假设编译器知道如何优化它。
如果你不使用结果,gcc -O3 yield
lock add DWORD PTR [rdi], 1
两者都是。
如果你确实使用了结果,那么 gcc -O3 会产生
mov DWORD PTR [rsp-24], edi
mov eax, 1
lock xadd DWORD PTR [rsp-24], eax
add eax, 1
ret
for preincrement,并省略了 add eax, 1
for post increment,所以从技术上讲,是的,pre-increment 的效率低于一次加法,但实际上与顺序内存访问相比相形见绌.
TLDR:别担心
一般的经验法则是在不立即评估值的情况下(即您只想增加 object/iterator),更喜欢在 STL 迭代器上使用预增量。这是因为一般来说预自增的实现比post自增更高效。
但是 std::atomic 呢?如果我 运行 静态分析(使用 PVS studio),我会收到一条警告说预增量应该更有效,但是当我查看预增量的实现时(在 Visual Studio 2015)它看起来效率低于 post-increment?
是否有在 STL 原子值上使用预增量而不是 post 增量的一般规则,还是特定于实现?
效率(在这个级别)总是具体实现。
例如,作为经验法则"prefer pre-increment for STL iterators"的反例,事实证明在实践中很少有编译器会为预增量和post-增量生成不同的代码。 (post-增量的伪造副本被优化得一无是处。)
我现在无法访问 windows,但在 gcc 中,区别在于
__atomic_fetch_add(&_M_i, 1, memory_order_seq_cst);
和
__atomic_add_fetch(&_M_i, 1, memory_order_seq_cst);
它们是内置的,所以你可以假设编译器知道如何优化它。
如果你不使用结果,gcc -O3 yield
lock add DWORD PTR [rdi], 1
两者都是。
如果你确实使用了结果,那么 gcc -O3 会产生
mov DWORD PTR [rsp-24], edi
mov eax, 1
lock xadd DWORD PTR [rsp-24], eax
add eax, 1
ret
for preincrement,并省略了 add eax, 1
for post increment,所以从技术上讲,是的,pre-increment 的效率低于一次加法,但实际上与顺序内存访问相比相形见绌.
TLDR:别担心