I particularly like Statistical Inference by George Casella and Roger Lee Berger.
You could also look at Introduction to Probability by Joseph K. Blitzstein and Jessica Hwang (available for free here: http://probabilitybook.net (redirects to drive)).
Should be noted that Casella’s book is… well… really great if you thought Spivak’s calculus and Rudin’s analysis to be fun books, especially the exercises.
string product{"not worked"} is initializing the string product to "not worked".
It's the same as std::string product; product = "not worked";
[&](job& my_job) { } is a lambda expression. & is capturing the variable by reference. my_job is the parameter being passed which is a pointer of type job.
> It's the same as std::string product; product = "not worked";
It's not exactly the same. The original called the converting constructor std::string::string(const char*). Your example calls the std::string default constructor, then the assignment std::string::operator=(const char*). Maybe you didn't mean literally the same, but where trying to illustrate the rough meaning, but the parent commenter said they were familiar with older versions of C++ so I think they'd already be familiar with converting constructors.
It might be more enlightening to say that all of the following are equivalent:
(I'm 90% sure about the last one but can't find documentation for it at the moment.) None of them call the copy constructor std::string::string(const std::string&) or copy assignment operator std::string::operator=(const std::string&), although in older versions of the C++ standard the last two required that the relevant assignment operators (std::string::operator=(const char*) and std::string::operator=(const std::string&) respectively) to be accessible even though it wasn't called.
For other combinations of types, these different syntaxes are not equivalent. For example, uniform initialisation (with the braces) won't allow narrowing conversions, such as short to int or double to float.
In practical terms, none. They are the same, and the same as using the curly braces.
From the POV of the standard, those are different kinds of initializations.
C++ has like 12 different ways of initializing variables, and the differences are quite confusing, but in practical terms in my experience I never had to care too much beside making sure native types are initialized to some specified value.
You can probably find some talks on YouTube talking about the initializations of c++, and 1h30m is probably not enought to cover all the details :')
For this particular example direct initialization i.e. std::string product("not worked"); would be preferred, as you end up using one call to constructor instead of two: default constructor followed by the move assignment.