给出以下工作代码(main.cpp):
#include <functional>
#include <iostream>
struct worker
{
std::function<bool(std::string)> m_callback;
void do_work(std::function<bool(std::string)> callback) // <--- this line
{
m_callback = std::bind(callback, std::placeholders::_1);
callback("hello world!\n");
}
};
// pretty boring class - a cut down of my actual class
struct helper
{
worker the_worker;
bool work_callback(std::string str)
{
std::cout << str << std::endl;
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work( [&](std::string data){ return the_helper.work_callback(data); });
}
编译为:-std=c++11 -O2 -Wall -Wextra -pedantic-errors -O2 main.cpp
我对有关的行(<-- this line
-第7行周围)发表了评论,在这里我认为使用void do_work(std::function<bool(std::string)>&& callback)
即使用&&
移动语义会更有效。 / p>
我从未真正使用过它,主要是因为我仍然不太了解它。
我的理解是:
void do_work(std::function<bool(std::string)> callback)
-将获取我传入的lambda的副本(我认为这是一个右值)。
void do_work(std::function<bool(std::string)> callback)
-将移动我传入的lambda,因为它是一个右值。
我对rvalue的粗略想法是任何临时变量。
问题:
我不是100%清楚的是,我写的正确吗?因此使用&&
是安全的。两者似乎都可以。
如果&&
方法不是传递像这样的lambda,是否也起作用?
the_helper.the_worker.do_work( [&](std::string data){ return the_helper.work_callback(data); });
我们传入std :: bind(...):
the_worker.do_work(std::bind(&helper::work_callback, the_helper, std::placeholders::_1));
答案 0 :(得分:3)
如果参数定义为右值引用,则必须传递临时值或将左值强制转换为右值,例如override fun onUpgrade(db: SQLiteDatabase, oldV: Int, newV: Int) {
if (oldVersion < 2) {
upgradeVersion2(db)
}
if (oldVersion < 3) {
upgradeVersion3(db)
}
if (oldVersion < 4) {
upgradeVersion4(db)
}
}
。
rvalue-references的语义是,调用者应期望掠夺传递的参数,使其成为有效但任意的,这主要是无用的。
但是,尽管具有掠夺许可,但接收右值引用的函数却没有任何掠夺义务。而且如果它没有明确地这样做,例如通过传递该许可证,那么它就不会通过,并且没有什么特别的事情发生。
您的代码就是这种情况。
虽然我会禁止使用std::move()
词汇表,但无论使用与否实际上并没有太大的不同。
答案 1 :(得分:1)
在这种情况下,无论您是通过值传递还是通过rval ref传递,都必须创建一个临时的std :: function,这是因为lambda并不是真正的std :: function。无论如何,都应在分配之前移动std :: function,以避免产生不必要的副本。
我建议在这种情况下按值传递,因为这样做比较灵活,并且如果传递lambda,则不会造成任何危害,因为std :: function通常会在适当的位置构造(因此临时不会移入函数;通常可以(通常会)忽略此移入)。