- 主题:关于lambda, move的语法问题
你是回他还是回我?ChatGPT的第三个方案居然可行
Doit([tt=std::ref(t)]()->Test { return std::move(tt.get()); }); // 可以编译
如果不用的话,只是加上lambda返回类型,还是不行
Doit([tt=std::move(t)]()->Test { return tt; }); // 无法编译
另外, Doit([tt=std::move(t)]()->Test { Test t1(tt); return t1; }); // 无法编译
但是应该是因为copy elision还是需要拷贝构造的定义,虽然不用。C++23说是可以取消这个要求了。
【 在 ziqin 的大作中提到: 】
: 有这么复杂么?明明是你自己写lambda习惯不好
: 你自己不写lambda的返回类型,系统识别出来,capture by move的lambda返回的是Test,default capture的lambda返回的是Test&
: 都是最基本的东西,搞得这么复杂。
: ...................
--
FROM 72.199.121.*
我的理解是,因为tt.get()是unnamed,引起了RVO; default capture里,实际上编译器认为所有被capture的也都是unnamed.
只有unnamed才能引起RVO
【 在 bihai 的大作中提到: 】
: 你是回他还是回我?ChatGPT的第三个方案居然可行
: Doit([tt=std::ref(t)]()->Test { return std::move(tt.get()); }); // 可以编译
: 如果不用的话,只是加上lambda返回类型,还是不行
: ...................
--
FROM 115.192.190.*
而且,你这个问题不在于怎么样可以编译通过,在于你想做什么。
我的理解是,你想把某个object放到异步代码里,但是又希望这个object是move过去的。如果你是这个目的,逻辑上,你最好使用unique_ptr,这样代码逻辑最清晰。
如果你一定不使用unique_ptr,那你的点在于Doit里呼叫opertor()时,怎么样可以move construct,因为你已经explicit delete copy ctor,所以我假设你的逻辑是Test完全不能copy的,那你就不应该使用copy elision或者RVO来绕过copty ctor。前面之所以return std::move(tt)编译不过去,是因为lambda默认是const的,也就是说tt是const的,编译器只会调用copy ctor,所以正确姿势应该是把lambda加上mutable,让编译器调用move ctor。但是这样会降低lambda的效率。
所谓采用reference_wrapper走RVO绕过copy ctor定义检查是典型跳坑,因为整个逻辑都不一样了。首先你传了个stack上的reference到异步代码里,然后这个异步代码在执行的时候还用这个reference绕开copy ctor的检查进行copy construct,妥妥出问题。
【 在 bihai 的大作中提到: 】
: 你是回他还是回我?ChatGPT的第三个方案居然可行
: Doit([tt=std::ref(t)]()->Test { return std::move(tt.get()); }); // 可以编译
: 如果不用的话,只是加上lambda返回类型,还是不行
: ...................
--
FROM 115.192.190.*