What's the best way to extend the scope of a variable for use in a lambda in c++?

Viewed 50

I have class:

class MyFunctionRunner{
  public:
      static callFunc(){
         func_(); //Calls the function that's set
      }
      static setFunc(std::function<void()> func){
         func_ = func; //Sets a function
      }
 private:
     static std::function<void()> func_;
 }

And a function:

void MyFunc(const std::string& a,const std::string& b){
   MyClass myObj{};

   MyFunctionRunner::setFunc(
     [&myObj](){
        myObj.setA(a); 
        myObj.setB(b);
   }); //Passes in a lambda function as a parameter that captures `myObj` as reference. 
 }

In my main, I have:

myFunc("a","b");
MyFunctionRunner::callFunc();

This compiles fine but hits a runtime error of "stack-use-after-return" because I guess it's by the time I run the function, myObj is out of scope? What can I do to extend the scope/lifetime of myObj reference ? Assume that MyClass's implementation (out of my control) has prevented copy constructor ("copy constructor is implicitly deleted...")

1 Answers

You can't extend the scope of the myObj variable without moving it into global/static memory. But what you can do instead is create the MyClass object in dynamic memory and change myObj to be a pointer to that object, and then you can capture a copy of that pointer in the lambda, eg:

void MyFunc(const std::string& a,const std::string& b){
   MyClass *myObj = new MyClass;

   MyFunctionRunner::setFunc(
     [myObj](){
        myObj->setA(a); 
        myObj->setB(b);
        delete myObj;
   });
}

In which case, you should consider using a smart pointer for safer memory management, eg:

void MyFunc(const std::string& a,const std::string& b){
   auto myObj = std::make_shared<MyClass>();

   MyFunctionRunner::setFunc(
     [myObj](){
        myObj->setA(a); 
        myObj->setB(b);
   });
}
Related