functions+globals work. Closures not.



  • Oh. The result is missing.

    Well, ... it's 5.



  • But I thought Closures preserve the local variables?

    C++ Closures capture things by value (copying) or by reference (storing a reference only). They don't magically extend a local object's life time. Apart from Lambdas being syntactic sugar, there is no other compiler magic going on. If you need to allocate some things dynamically (as in dynamic life-time), you have to say so explicitly (see make_shared, for example).

    I don't know Python. What does this snippet do w.r.t. "the thing that val refers to" ?

    Chances are that the code I posted (using a shared_ptr) is exactly what you want.

    Keep in mind that in C++ -- unlike in some of the other, supposedly more modern languages -- there is no implicit indirection.



  • Thanks for your correct and working answer. But I'm confused. I thought C++ "closures" keep local variables alive, when captured. But It looks like I was wrong 😞 I have to copy them. Or allocate then on the heap like you did.



  • I thought C++ "closures" keep local variables alive

    No. They don't.

    Since you refer to this state from many closures and you don't want each closure to store a seperate independent copy, I suggest you go with the shared_ptr approach so that each of the closures you created inside this function call share this state. Each time, you should capture this shared_ptr by copy.

    I'm pretty sure that your python code is semantically equivalent. Under the hood, python creates an object storing a 5 on the heap and simply attaches the address of that object to the closure. As I said, there is NO IMPLICIT INDIRECTION in C++. If you want dynamic allocation, you have to say that. If you want to use pointers, you have to say that.



  • Martin Kalbfuß schrieb:

    Thanks for your correct and working answer. But I'm confused. I thought C++ "closures" keep local variables alive, when captured. But It looks like I was wrong 😞 I have to copy them. Or allocate then on the heap like you did.

    C++ doesn't (can't) keep local variables alive, because the core language has neither a GC nor any means of reference-counting stuff.
    (Yes, there's shared_ptr now, but it's a library thing, not a core-language thing)
    And without that, it wouldn't be possible to determine when those variables can be released/destroyed again.

    What you can (and IMO should) do, is, to put all the required variables into a struct/class, and then capture a shared_ptr that own's an instance of that struct/class by value.

    If you capture the variables themselves by value, each lambda function will have it's own copy of the variables. Which is probably not what you want.

    And... we're a german forum here. Please post in german (your name suggest that you speak german).



  • Martin Kalbfuß schrieb:

    OK. So here is a working python example. I would like to have a behaviour like this in C++.

    >>> def outer():
    ...     var = 5
    ...     def inner():
    ...             return var
    ...     return inner
    ... 
    >>> outer()()
    

    I guess Python works like Ruby (although I never used Python). In Ruby, every Closure holds references to the surrounding variables so that they don't get garbage collected when you leave the outer function. But in C++, variables on the stack automatically get destroyed after leaving their scope. So the reference you hold is a dangling reference.



  • When I think about it again it's clear that C++ can't do this like python or perl. It isn't garbage collected. Anyway. My python example was still wrong.

    Thanks for your help. Problem solved!



  • Ups. Tschuldigung. Ich bin eher selten in deutschen Foren unterwegs. Hab gar nicht richtig geschaut. Aber um so besser. Das macht's wesentlich angenehmer.



  • Martin Kalbfuß schrieb:

    Ups. Tschuldigung. Ich bin eher selten in deutschen Foren unterwegs. Hab gar nicht richtig geschaut. Aber um so besser. Das macht's wesentlich angenehmer.

    🤡

    Was ist denn falsch an dem Pythoncode?



  • die variable ist in Closures nur lesbar und kann nicht verändert werden. Man kann dies umgehen, in dem man die Variable in einen Behälter steckt.

    def closure():
        container = [0]
        def inc():
           container[0] += 1
        def get():
           return container[0]
        return inc, get
    

    `

    i, g = closure()

    g()

    0

    i()

    i()

    print g()

    2

    `


Anmelden zum Antworten