简体   繁体   English

C ++ lambda中的静态变量

[英]Static variables in C++ lambdas

The following code works fine: 以下代码工作正常:

#include <iostream>
#include <functional>

std::function<int (void)> get_incrementer() {
    return []() {
        static int count = 0;
        return count++;
    };
}

int main() {
    using std::cout;

    auto incrementer = get_incrementer();

    cout << incrementer() << std::endl;
    cout << incrementer() << std::endl;

    return 0;
}

But if you capture a local variable by reference instead, it suddenly results in undefined behaviour, presumely because at call-time that location on the stack is being used by something else. 但是,如果您通过引用捕获局部变量,它会突然导致未定义的行为,因为在调用时,堆栈上的位置正被其他东西使用。

std::function<int (void)> get_incrementer() {
    int count = 0;

    return [&count]() {
        return count++;
    };
}

Why does the compiler allow it though? 为什么编译器允许它呢? I expected the compiler to either not allow this (it seems trivial to check for this case) or change the storage duration of the local variable. 我希望编译器要么不允许这样做(检查这种情况似乎微不足道)或者改变局部变量的存储持续时间。

C++ allows it because C++ is not a safe language. C ++允许它,因为C ++不是一种安全的语言。 And while this case may be "trivial" to check for (and personally, I don't agree that it's trivial, but I'm not a compiler writer), there are plenty of other cases that are not trivial to check for. 虽然这个案例可能是“微不足道”来检查(而且个人而言,我不同意这是微不足道的,但我不是编译器编写者),还有很多其他案例并不容易检查。

C++ is not in the business of fixing your broken code for you. C ++不是为您修复损坏的代码。 It does exactly and only what you tell it to, even if it's massively unwise. 它确实只是你告诉它的,即使它是非常不明智的。

Furthermore, it's not entirely clear exactly what it is that you were intending this code to do. 此外,还不完全清楚你打算用这个代码做什么。 For example, these are two completely different things: 例如,这些是完全不同的两件事:

std::function<int (void)> get_incrementer() {
    return []() {
        static int count = 0;
        return count++;
    };
}

std::function<int (void)> get_incrementer() {
    int count = 0;
    return [count]() mutable {
        return count++;
    };
}

In the first case, every instance of the returned function will share the same increment count. 在第一种情况下,返回函数的每个实例将共享相同的增量计数。 In the second case, each time you call get_incrementer , you will get a separate object with it's own increment count. 在第二种情况下,每次调用get_incrementer ,您将获得一个单独的对象,其中包含自己的增量计数。

Which one did the user want? 用户想要哪一个? It's not clear. 目前尚不清楚。 So you can't just willy-nilly "correct" it. 所以你不能随便“纠正”它。

You explicitly tell the compiler that you want to take the variable by reference, so it assumes that you have your reasons and does what you tell it to do. 您明确告诉编译器您希望通过引用获取变量,因此它假定您有自己的理由并按照您的要求执行操作。

You are the master, the compiler is merely there to serve your needs and obey your wishes. 您是主人,编译器只是满足您的需求并遵守您的意愿。 It might warn you in certain cases when it thinks you are doing something particularly strange, but if you insist, it respects you authority and compiles that strange looking code. 它可能会在某些情况下警告你,当它认为你正在做一些特别奇怪的事情时,但是如果你坚持,它会尊重你的权威并编译那些奇怪的代码。

Using references to local variables after the local variable went out of scope is always undefined behavior and won't do any good, using a lambda to do it is not all that special. 在局部变量超出范围之后使用对局部变量的引用总是未定义的行为并且不会有任何好处,使用lambda来完成它并不是那么特别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM