c++ - 使用 lambdas 移动

标签 c++ lambda c++11

在使用 lambda 函数时,假设您决定复制一个变量(使用 [=] 符号)。如果您不再引用该变量,编译器是否允许将其移动到生成的函数对象中?

编辑:例如,我编写了一个片段来跨线程移动调用。这是一个这样做的示例。

extern "C" __declspec(dllexport) void parser_file_updated(Parser* p, const char* filename, int offset, int added) {
     std::string file(filename);
     p->make_call([=]() {
         p->file_updated(std::move(file), offset, added);
     });
}

但很明显,文件变量不需要超过 lambda 定义——事实上,lambda 只被调用一次,所以我移动了拷贝。

最佳答案

If you never reference that variable again, is the compiler allowed to move it into the resultant function object?

没有。允许编译器用移动替换拷贝的唯一情况与允许执行复制省略的情况完全相同。这些情况包括按值返回本地对象或使用临时对象初始化对象。在这些情况下,允许编译器通过使源和目标相同的对象来删除拷贝。如果编译器由于某种原因无法做到这一点,则必须将源对象视为相对于重载决议的右值,以便为目标对象选择适当的构造函数。但是,在您的情况下,文件是左值,上述情况均不适用。您必须使用显式移动。

不幸的是,C++11 没有“移动捕获”的语法。恕我直言,这是一种耻辱。但 std::bind 支持这一点。应该可以将 std::bind 与这样的 lambda 表达式结合起来:

void foo(char const* p) {
   string s = p;
   auto fun = bind([](string const& s){
      ...
   },move(s));
   fun();
}

以便将字符串移动到函数对象中。

如果你打算只调用这个函数一次并且想再次将字符串移出函数对象,你可以使用非常量引用:

void foo(char const* p) {
   string s = p;
   auto fun = bind([](string & s) {
      some_other_func(move(s));
   },move(s));
   fun();
}

请注意,如果您不想在这里使用 bind 而是让 lambda 对象的构造函数创建 s 的拷贝,则将字符串移出函数对象需要 mutable 关键字:

void foo(char const* p) {
   string s = p;
   auto fun = [=]() mutable {
      //            ^^^^^^^
      some_other_func(move(s));
   };
   fun();
}

因为否则闭包类型的 operator() 函数将是 const 限定的,这反过来又使 s 成为 const 限定的字符串。

在 C++14 中,lambda 捕获子句变得更加灵活。我们现在可以写

void foo(char const* p) {
   string s = p;
   auto fun = [s=move(s)]() mutable { // #1
      some_other_func(move(s));       // #2
   };
   fun();
}

其中 #1 将字符串值移入 lambda 对象,而 #2 将字符串值移出(取决于 some_other_func 的准确声明方式)。

关于c++ - 使用 lambdas 移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4433109/

相关文章:

java: Arrays.sort() 与 lambda 表达式

c++ - Wangle:/usr/local/lib/libfolly.so: 对 boost::re_detail_106000 的 undefined reference

c++ 具有函数的类继承

python - python中的两个相邻列表

c++ - 我如何在 C++11 中解决 SICP 2.4

c++ - 将 std::condition_variable 与 atomic<bool> 一起使用

c++11 - C++ 中的集合

c++ - LNK1104 : cannot open file 'wxbase28d.lib'

c++ - 如何使用 lambda 函数打印一对<>?

c++ - 使用指向成员的指针时,如何通过作用域解析运算符获取类成员的地址?