为什么需要"std::function::operator=(F &&)"来制作临时的"std::function"?
Why `std::function::operator=(F &&)` is required to make a temporary `std::function`?
显然std::function::operator=(F &&f)
需要完全按照std::function(std::forward<F>(f)).swap(*this);
的行为。
除非我错过了什么,否则这个定义会导致一些多余的移动:
#include <functional>
#include <iostream>
struct A
{
A() {std::cout << "A()n";}
A(const A &) {std::cout << "A(const A &)n";}
A(A &&) {std::cout << "A(A &&)n";}
A &operator=(const A &) {std::cout << "A &operator=(const A &)n"; return *this;}
A &operator=(A &&) {std::cout << "A &operator=(A &&)n"; return *this;}
~A() {std::cout << "~A()n";}
void operator()() const {}
};
int main()
{
std::function<void()> f;
f = A{};
}
指纹:
A() // Created by `A{}` A(A &&) // Moved into temporary `std::function`, but what's the point? A(A &&) // Moved into `f` ~A() ~A() ~A()
(在GCC 7.2和Clang 3.8上测试(
问题:为什么我们不能通过将复制/移动(取决于值类别(直接复制到 LHS 存储中来消除一次移动?
编辑:我不是在问为什么没有优化这一举动,而是为什么首先要这样做。
为什么有两个动作?
当构造std::function
的临时时,被调用的构造函数是
template< class F >
function( F f );
这是按值传递的,因此第一次移动实际上是移动到此构造函数的参数中,而第二次移动是移动到临时移动。基本上,std::function
的典型实现存储指向其可调用目标的指针,因此交换指针足以满足其swap
函数,这不会涉及其可调用目标的任何复制/移动。
为什么不直接将 RHS 复制/移动到 LHS 存储中?
由于 LHS 中存储的可调用目标的类型可能与 RHS 的类型不同,因此无法直接执行复制/移动。
swap()
为什么参与其中?
这称为复制和交换习惯用法,它表现为具有强异常安全性的赋值。
相关文章:
- Confusion: decltype vs std::function
- 为什么 std::function 可以作为 std::not2 的参数?
- 'max'匹配'std::function<const int &(const int &, const int &)>'无过载
- 传递给std::function template的template参数究竟代表什么
- 绑定派生类方法C++从实例范围之外的分隔 std::function 变量调用
- 将函数包装器转换为 std::function
- 类型擦除的std::function与虚拟函数调用的开销
- C++ std::function 对于类 exept 的所有实例都是空的(只有 Visual2019 编译器问题)
- 如果模板没有可变参数,则 Lambda 被推导出为 std::function
- 将 lambda 表达式传递给 std::function in C++
- 模板类的部分模板专用化,如 std::function
- 可变参数模板参数扩展 类型为 std::function 的类成员
- 从 std::function in C++ 访问模板化 lambda
- 什么是 std::function::argument_type 的替代品?
- C++派生类重载函数(带有 std::function 参数)不可见
- 如何在 qi 符号表中使用 std::function
- 将 std::function 与模板一起使用
- C++ 事件管理器的回调,使用 std::function 和 std:bind 以及派生类作为参数
- 我需要在 std::function 上使用 unique_ptr 吗?
- 如何将函数指针从 std::function 传递到 Linux 克隆?