【发布时间】:2020-11-23 04:18:04
【问题描述】:
std::function 的构造函数看起来像这样(至少在 libc++ 中):
namespace std {
template<class _Rp, class ..._ArgTypes>
function {
// ...
base_func<_Rp(_ArgTypes...)> __func;
public:
template<typename _Fp>
function(_Fp __f) : __func(std::move(__f)) {}
template<typename _Fp>
function& operator=(_Fp&& __f) {
function(std::forward<_Fp>(__f)).swap(*this);
return *this;
}
};
}
它提供了来自任意函子的构造函数和来自任意函子的赋值运算符。构造函数使用按值传递,但赋值运算符使用按通用引用传递。
我的问题是为什么 std::function 的构造函数不像赋值运算符那样通过通用(转发)引用传递?例如,它可以这样做:
namespace std {
template<class _Rp, class ..._ArgTypes>
function {
// ...
base_func<_Rp(_ArgTypes...)> __func;
public:
template<typename _Fp>
function(_Fp&& __f) : __func(std::forward<_Fp>(__f)) {}
template<typename _Fp>
function& operator=(_Fp&& __f) {
function(std::forward<_Fp>(__f)).swap(*this);
return *this;
}
};
}
我很好奇这里区别对待赋值和构造函数的基本原理是什么。谢谢!
【问题讨论】:
-
因为that's what the language specification requires。请注意,您的示例存在缺陷,因为您没有移动构造函数,因此唯一的选择是复制。如果你添加
Func(Func&& f) { std::cout << "move ctor is called" << std::endl; },那么你会看到它被移动了。 -
如果您查看任何接受可调用参数的标准库函数,您会发现它们都按值接受这些参数。
-
您的最后一次编辑使问题无效。而且您也缺少默认构造函数。 :godbolt.org/z/3K7MoE不能再复制了!
-
@RaymondChen 感谢您的回答。经过多次编辑后,我意识到我的问题没有意义。我还意识到,如果正确完成,按值传递也可以避免复制。我已经修改了问题。
标签: c++ c++11 templates generics