[问题] bind object(std::bind)内部用copy?

楼主: Caesar08 (Caesar)   2016-07-13 22:48:49
如题
先定义一下名词
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
作者: PkmX (阿猫)   2016-07-14 01:26:00
1你要考虑bind的结果被呼叫前a被修改的情况或是同一个bind的结果被呼叫多次的情况啊2的话要写成bind(test_mov, bind(move<A&>, move(a)))();但是这个结果就只能呼叫一次
作者: cplusplus (对的人难寻)   2016-07-14 02:38:00
确实bind传回functor是要能之后用呀,不然要它干嘛?XD所以没办法用最后提到A&&那个也很正常,不太合使用情境
作者: PkmX (阿猫)   2016-07-14 02:41:00
其实我觉得有了lambda以后 bind就很少用了XD
作者: cplusplus (对的人难寻)   2016-07-14 02:42:00
如上面仁兄所说,一般用rval ref传入只能用一次,参数通常就被修改掉了(如果不会也没需要用rval ref当参数)SORRY切断了。同意多用lamda,好处多多XD少了b
作者: PkmX (阿猫)   2016-07-14 02:46:00
是我切断你了XD C++14可以做move capture 2就可以直接写成[a{move(a)}]() mutable { test_mov(move(a)); }();
作者: cplusplus (对的人难寻)   2016-07-14 03:06:00
先撇开bind不说,想了一下还想不到需要这样用的情境~不知原有啥用到的例子吗??smart pointer应用?
作者: PkmX (阿猫)   2016-07-14 11:51:00
多次呼叫你可以考虑类似generator的应用auto f = std::bind([](int& n) { return n++; }, 0);f(); f(); f();用lambda吧XD [=]() mutable { test_mov(std::move(a)); }如果 ??? 是 = 就和 std::bind 是一样的啊可是bind那样写也是没办法处理func是吃rvalue ref的情况http://melpon.org/wandbox/permlink/i6hpL0VL93nEqzbz这个版本用lambda可以达到你要的效果 建立时先复制args一次然后因为只用一次 他会直接把复制的args move给func但若func要lvalue ref 会用template版本转成lvalue ref给它
作者: cplusplus (对的人难寻)   2016-07-14 17:21:00
C++提供很多机制可以用,但怎么用也蛮重要,有时候是
作者: PkmX (阿猫)   2016-07-14 17:21:00
虽然我觉得arg_ref_t改一改也可以给bind用
作者: PkmX (阿猫)   2016-07-14 20:11:00
查了一下Scott Meyers认为C++14以后已经没有使用bind的必要C++14对lambda新增的features让他可以完全取代bind的功能所以只是看用哪个写比较好懂好维护这样

Links booklink

Contact Us: admin [ a t ] ucptt.com