Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

On this wikipedia page I have found the following sentence regarding closures in C++11:

C++11 closures can capture non-local variables by copy or by reference, but without extending their lifetime.

Does this mean that an existing closure might refer to a non-local variable that has already been de-allocated? In such a case, is there any special care / best practice that one has to follow when using captured non-local variables inside a C++ closure?

share|improve this question
    
The same practices you follow when calling any function, surely. –  James Aug 16 '12 at 20:57
    
I am not sure if this is sufficient. I could pass the closure as an argument to some object's method. That object could store the closure internally and then invoke it when its captured non-local variables have become invalid. Is this scenario possible? What would happen then? –  Giorgio Aug 16 '12 at 21:01
    
@Giorgio: The code would invoke undefined behaviour. But how often is it that you don't know what the called function does with your passed functor? –  sellibitze Aug 16 '12 at 21:06
    
@sellibitze: For that matter, also dereferencing an uninitialized pointer is undefined behaviour (normally leading to a crash), I do not have a problem with undefined behaviour. I am just trying to identify the problematic scenarios and how to avoid them. –  Giorgio Aug 16 '12 at 21:12
add comment

1 Answer

up vote 4 down vote accepted

Does this mean that an existing closure might refer to a non-local variable that has already been de-allocated?

Yes. Extending an object's life-time which was allocated on the stack beyond the execution of the outer function seems to be somewhere between unreasonable and impossible. Also, the compiler won't try to check whether such an extension is needed and magically allocate the object on the heap or something like this. As a programmer you have to be explicit about what is supposed to happen with respect to allocation. If you want to use the free store (aka heap), use the free store. There is nothing magical going on with lambdas. If you make your closure object store the address of some other object that used to live on the stack and you try to access it after it's gone, the behaviour is undefined.

any special care / best practice that one has to follow when using captured non-local variables inside a C++ closure?

Just make sure that your lambda does not capture by reference if the lambda object (or a copy of it) outlives the scope it (or the original) was created in. For example, using a lambda which captures by reference as argument to some of the algorithms you find in the algorithm header is perfectly fine.

share|improve this answer
    
Thanks, I think I get it. Intuitively I can consider the closure as an object (or, in particular, as a functor) with a reference member variable that is initialized to the captured non-local variable. Then I have the same risks I would have when moving around such an object. –  Giorgio Aug 16 '12 at 21:38
    
"Extending an object's life-time which was allocated on the stack beyond the execution of the outer function seems to be somewhere between unreasonable and impossible.": In order to obtain this I guess I would have to allocate a smart pointer on the stack, and let the closure capture that. Then the object pointed to by the smart pointer would live as long as the closure is around. –  Giorgio Aug 16 '12 at 21:42
    
@Giorgio: Your intuition is more than just reasonable; it's how lambda's must behave. The standard even says that the lambda must be an object, with a type - it's no magic construct. –  MSalters Aug 17 '12 at 7:22
    
@MSalters: Thanks. I am just trying to build the right intuition. AFAIK, lambdas in other languages behave differently, e.g. in Scheme data objects referenced by variables captured by a lambda continue to exist as long as the lambda exists. I just had to get the right C++ semantics into my head. –  Giorgio Aug 17 '12 at 7:40
    
@Giorgio: That's because Scheme is GC. The behavior is again not specific to lambda's; Scheme objects are always only referenced by variables. In C++, variables can be objects or reference objects or point to objects. –  MSalters Aug 17 '12 at 8:16
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.