Mathieu
Mathieu

Reputation: 330

c++ thread: wrap thread function in lambda

#include <iostream>
#include <thread>
    
class MyClass {
public:
    MyClass(int val) : val_(val) {}
    
    int val_{0};
};
    
void threadFunction(MyClass myObj) {
    // do something ...
}
    
int main() {
    MyClass obj(42);
 
    std::thread t1(threadFunction, obj); 
    std::thread t2([=]() {
        threadFunction(obj);
    });
    
    t1.join();
    t2.join();
    
    return 0;
}

In thread t1, I called threadfunction directly whereas in thread t2, I put the call of threadFunction in a lambda.

Are these two ways of thread creation equivalent?

Upvotes: 0

Views: 65

Answers (1)

wohlstad
wohlstad

Reputation: 29009

The only difference between the alternatives is related to copies or moves of the MyClass obj object.

It can be observed by adding copy and move constructors with prints:

class MyClass {
public:
    MyClass(int val) : val_(val) {}

    MyClass(MyClass const & other)
    {
        std::cout << "copy\n";
        val_ = other.val_;
    }

    MyClass(MyClass && other)
    {
        std::cout << "move\n";
        val_ = other.val_;
    }

    int val_{0};
};

In the first case, the std::thread constructor will make a copy of obj, and then it will be moved when the function will be invoked by the new thread.

See demo1, with output:

copy
move

In the second case, there will be an additional copy when the lambda will be executed and will call threadFunction.

See demo2, with output:

copy
move
copy

A third alternaive is the use the lambda with capture by reference.
This will reduce it to only one copy (when the lambda will call threadFunction).

See demo3, with output:

copy

Note that this third option relies on the fact that obj is not destroyed while the thread is being launched (otherwise a race condition will occue). In your case it is OK because the threads are joined while obj is still alive.

Upvotes: 2

Related Questions