为什么std::future<T>和std::shared_future<T>不提供成员swap()?
Why do std::future<T> and std::shared_future<T> not provide member swap()?
C++标准库中的各种classes都有成员交换函数,包括一些多态的classes,如std::basic_ios<CharT>
。模板 class std::shared_future<T>
显然是值类型,而 std::future<T>
是仅移动值类型。有什么特别的原因,他们不提供swap()
成员函数吗?
在 C++11 std::move
支持之前,成员交换是一个巨大的性能提升。例如,您可以通过这种方式将一个矢量移动到另一个位置。它也用于 vector
调整大小,这意味着插入向量向量并不是完全的性能自杀。
在 std::move
到达 C++11 之后,std::swap
的默认实现有许多有时为空的类型:
template<class T>
void swap( T& lhs, T& rhs ) {
auto tmp = std::move(rhs);
rhs = std::move(lhs);
lhs = std::move(tmp);
}
基本上和自定义编写的一样快。
具有 swap
个成员的现有类型不太可能丢失它们(至少立即丢失)。但是,扩展新类型的 API 应该是合理的。
如果 std::future
基本上是 std::unique_ptr< future_impl >
的包装器,那么上面的代码将需要 4 次指针读取、3 次指针写入和一个分支。内联它的优化编译器1 可以将其减少到 2 个指针读取和 2 个指针写入(例如使用 SSA2),这是优化的 .swap
成员函数可以做什么。
1 所以它知道对 lhs
和 rhs
的中间访问永远不会发生,因此 tmp
的存在可以被消除为-if 一旦它证明 tmp
是空的,因此有一个空操作 dtor。
2 Static single assignment,您可以在其中分解程序,以便对原语的每次赋值都会创建一个全新的变量(带有元数据)。然后证明该变量的属性,并消除多余的。
C++标准库中的各种classes都有成员交换函数,包括一些多态的classes,如std::basic_ios<CharT>
。模板 class std::shared_future<T>
显然是值类型,而 std::future<T>
是仅移动值类型。有什么特别的原因,他们不提供swap()
成员函数吗?
在 C++11 std::move
支持之前,成员交换是一个巨大的性能提升。例如,您可以通过这种方式将一个矢量移动到另一个位置。它也用于 vector
调整大小,这意味着插入向量向量并不是完全的性能自杀。
在 std::move
到达 C++11 之后,std::swap
的默认实现有许多有时为空的类型:
template<class T>
void swap( T& lhs, T& rhs ) {
auto tmp = std::move(rhs);
rhs = std::move(lhs);
lhs = std::move(tmp);
}
基本上和自定义编写的一样快。
具有 swap
个成员的现有类型不太可能丢失它们(至少立即丢失)。但是,扩展新类型的 API 应该是合理的。
如果 std::future
基本上是 std::unique_ptr< future_impl >
的包装器,那么上面的代码将需要 4 次指针读取、3 次指针写入和一个分支。内联它的优化编译器1 可以将其减少到 2 个指针读取和 2 个指针写入(例如使用 SSA2),这是优化的 .swap
成员函数可以做什么。
1 所以它知道对 lhs
和 rhs
的中间访问永远不会发生,因此 tmp
的存在可以被消除为-if 一旦它证明 tmp
是空的,因此有一个空操作 dtor。
2 Static single assignment,您可以在其中分解程序,以便对原语的每次赋值都会创建一个全新的变量(带有元数据)。然后证明该变量的属性,并消除多余的。