60

我正在阅读有关网络关闭的信息。我想知道 C++ 是否有内置的闭包工具,或者是否有任何方法可以在 C++ 中实现闭包?

4

6 回答 6

41

最新的 C++ 标准C++11具有闭包。

http://en.wikipedia.org/wiki/C%2B%2B11#Lambda_functions_and_expressions

http://www.cprogramming.com/c++11/c++11-lambda-closures.html

于 2012-09-28T07:08:24.700 回答
21

如果您将闭包理解为对具有嵌入式、持久性、隐藏和不可分离上下文(内存、状态)的函数的引用,那么是的:

class add_offset {
private:
    int offset;
public:
    add_offset(int _offset) : offset(_offset) {}
    int operator () (int x) { return x + offset; }
}

// make a closure
add_offset my_add_3_closure(3);

// use closure
int x = 4;
int y = my_add_3_closure(x);
std::cout << y << std::endl;

下一个修改它的状态:

class summer
{
private:
    int sum;
public:
    summer() : sum(0) {}
    int operator () (int x) { return sum += x; }
}

// make a closure
summer adder;
// use closure
adder(3);
adder(4);
std::cout << adder(0) << std::endl;

不能从外部引用(访问)内部状态。

根据你的定义,一个闭包可以包含对多个函数的引用,或者两个闭包可以共享相同的上下文,即两个函数可以共享相同的持久状态。

闭包意味着不包含自由变量——它与只有私有属性和只有公共方法的类相当。

于 2013-10-19T09:18:55.523 回答
19

是的,这显示了如何在不使用仿函数的情况下实现具有状态的函数。

#include <iostream>
#include <functional>


std::function<int()> make_my_closure(int x){
    return [x]() mutable {   
        ++x;
        return x;   
    };
}

int main()
{
    auto my_f = make_my_closure(10);

    std::cout << my_f() << std::endl; // 11
    std::cout << my_f() << std::endl; // 12
    std::cout << my_f() << std::endl; // 13

     auto my_f1 = make_my_closure(1);

    std::cout << my_f1() << std::endl; // 2
    std::cout << my_f1() << std::endl; // 3
    std::cout << my_f1() << std::endl; // 4

    std::cout << my_f() << std::endl; // 14
}

我忘记了引入未定义行为的 mutable 关键字(clang 版本正在返回垃圾值)。实施后,关闭工作正常(在 GCC 和 clang 上)

于 2015-11-11T14:39:29.877 回答
9

我怀疑这取决于你所说的关闭是什么意思。我一直使用的含义意味着某种垃圾收集(尽管我认为它可以使用引用计数来实现);与其他语言中的 lambdas 捕获引用并使被引用对象保持活动状态不同,C++ lambdas 要么捕获一个值,要么所引用的对象 保持活动状态(并且引用很容易悬空)。

于 2012-09-28T07:29:54.833 回答
7

是的,C++11 有名为lambdas的闭包。

在 C++03 中没有对 lambdas 的内置支持,但是有Boost.Lambda实现。

于 2012-09-28T07:10:29.407 回答
0

严格来讲。“关闭”只是 LISP。使用 Let 返回 lambda 作为最后一个命令。'让拉姆达'。这仅适用于 LISP,因为具有词法作用域的无限范围。在知道之前,我不知道有任何其他语言本机支持这一点。

(defun my-closure ()
   (let ((cnt 0))
      (lambda () 
         (format t "called : ~A times" (incf cnt)))))
于 2020-04-12T16:02:18.780 回答