0

This lambda definition:

auto lambda = [](int i)->std::string {
    return std::to_string(i);
};

Is equivalent to this functor:

struct Lambda {
    std::string operator()(int i) { return std::to_string(i); }
};

Consider this class definition whose purpose is to hold a function pointer (not a std::function object):

struct Holder {
    using Callback = std::string(*)(int);

    void SetCallback(Callback cb) { mCallback = cb; }
    Callback GetCallback() const  { return mCallback; }

private:
    Callback mCallback;
};

Then, else where in code, a function stores an actual pointer in a Holder, followed by a use of the function callback:

void Store(Holder& holder) {
    auto toStr = [](int i)->std::string {
        return std::to_string(i);
    };

    holder.SetCallback(toStr);
}

void Transform(int i) {
    Holder h;
    Store(h);
    auto cb = h.GetCallback();
    std::cout << cb(42);      // Expected this to crash, but doesn't.
}

QUESTION:

Why doesn't Transform crash?

The Store function creates a local lambda, and then stores a pointer to it in Holder. Holder stores a pointer to the callback, not a std::function. Presumably, the toStr object goes out of scope at the end of Scope. When Transform gets the callback pointer auto cb = h.GetCallback(), isn't it getting a pointer to an expired object?

My test was done in MSVC 2022

Dess
  • 2,064
  • 19
  • 35
  • 1
    When you decay a lambda into a function pointer the compiler stamps out a normal function for the pointer to point to. – NathanOliver Apr 17 '23 at 00:30
  • 2
    Worth noting - _crashes_ are the result of Undefined Behavior, and you should not anticipate how Undefined Behavior behaves. – Drew Dormann Apr 17 '23 at 00:33
  • 1
    The question is if this is really UB because I would say that functions have no lifetime, so a function pointer can not expire. – gerum Apr 17 '23 at 07:11

0 Answers0