如题
先定义一下名词
bind指的是std::bind
bind object指的是std::bind的return value(standard也没说他叫什么名字,所以我就取这名字了)
g指的是bind object实际会呼叫的function(也就是bind的第一个parameter)
根据C++ standard
如果传给bind的是reference_wrapper,那最后会用reference的方式传给g
可是如果传给bind的不是reference_wrapper(同时也不是bind object与placeholder)
那就会先把argument copy到bind object里面
而且在bind object呼叫g时,这些data会以l-value的方式传给g
这样就会有两个问题
1.
struct A{};
void test_cpy(A){}
void test_ref(A &){}
int main()
{
A a;
bind(test_cpy,a)(); //copy 2次
bind(test_cpy,ref(a))(); //copy 1次
bind(test_ref,a)(); //copy 1次
bind(test_ref,ref(a))(); //no copy
bind(test_cpy,move(a))(); //move 1次,copy 1次
}
可是实际上,改良后的bind可以是
bind(test_cpy,a)()用reference(bind object)与copy(test_cpy)来取代2次copy
bind(test_ref,a)()用reference(bind object)与reference(test_cpy)来取代1次co
py
bind(test_cpy,move(a))()可以改用move 2次
也可以是
bind(test_cpy,a)()用copy(bind object)与move(test_cpy)来取代2次copy
bind(test_cpy,move(a))()可以改用move 2次
(以上两种bind是不同的实作方式)
不论是哪种改良后的bind,都比原本的好
为什么bind要设计成这样?这样效能不是有很大问题吗?
(题外话:bind是从boost那边来的)
2.
void test_mov(A &&){}
int main()
{
A a;
bind(test_mov,move(a))(); //这边打什么,compile都不过通过
}
原因很简单,bind object在呼叫g的时候,data会用l-value的方式传给g
结果现在g的parameter是A &&
解法就是把test_move(A &&)改成别的,但是这解法对很多已存在的function是行不通的
所以,bind为什么要设计成这样呢?
(bind被引进到standard是C++11的时候,但是C++11最大的改革之一就是move,难道委员
会
我唯一想到的可能原因,就是,bind是要拿来copy整个g的呼叫方式(可以拿来当callbac
k?
可是就算是这原因,那呼叫g的时候
非reference_wrapper的data且g的parameter非l-value reference时也应该用move才对啊
到底是什么原因,导致bind有这样奇怪的行为呢?
可能的解法在#1NXvUCDP