C++ thread pass value invoke constructor once and deconstructor many times,while pass ref it only invoke both constructor and deconstructor once
//Pass thread value type
//Model//Util.h #ifndef Util_H #define Util_h #include <ctime> #include <chrono> #include <iostream> #include <sstream> #include <thread> #include <uuid/uuid.h> #include <vector> using namespace std; class Util { public: static char *uuidValue; static char *dtValue; static int num; Util(); ~Util(); char *getTimeNow(); char *getUuid(); static void printUuidNum3(int x,Util ul); static void printNumUuid4(int x,Util ul); void mt5(int x,int y,Util ul); }; #endif //Model//Util.cpp #include "Model/Util.h" char *Util::dtValue = (char *)malloc(20); char *Util::uuidValue = (char *)malloc(40); int Util::num = 0; void Util::mt5(int x, int y, Util ul) { thread t1(printUuidNum3, x, ul); t1.join(); thread t2(printNumUuid4, y,ul); t2.join(); cout << getTimeNow() << ",finished in void Util::mt5(int x,int y,Util ul)!" << endl; } void Util::printNumUuid4(int x, Util ul) { for (int i = 0; i < x; i++) { cout << i << "," << ul.getUuid() << endl; } } void Util::printUuidNum3(int x, Util ul) { for (int i = 0; i < x; i++) { cout << ul.getUuid() << "," << i << endl; } } Util::Util() { cout << ++num << ",In constructor!" << endl; } Util::~Util() { cout << --num << ",In deconstructor!" << endl; } char *Util::getUuid() { uuid_t newUUID; uuid_generate(newUUID); uuid_unparse(newUUID, uuidValue); return uuidValue; } char *Util::getTimeNow() { time_t rawTime = time(NULL); struct tm tmInfo = *localtime(&rawTime); strftime(dtValue, 20, "%Y%m%d%H%M%S", &tmInfo); return dtValue; }
//main.cpp #include "Model/Util.h" using namespace std; void mt2(int x,int y); int main(int args, char **argv) { mt2(atoi(argv[1]), atoi(argv[2])); } void mt2(int x,int y) { Util ul; ul.mt5(x,y,ul); }
Compile
g++ -g -std=c++2a -I. *.cpp ./Model/*.cpp -o h1 -luuid -lpthread;
Run
time ./h1 5 5;
As the above snapshot illustrates,the constructor run only once,but the deconstructor run 8 times which confused me.
The constructor create the class instance only once,however the deconstructor can destory or dispose the instance 8 times.
//Model//Util.h #ifndef Util_H #define Util_h #include <ctime> #include <chrono> #include <functional> #include <iostream> #include <sstream> #include <thread> #include <uuid/uuid.h> #include <vector> using namespace std; class Util { public: static char *uuidValue; static char *dtValue; static int num; Util(); ~Util(); char *getTimeNow(); char *getUuid(); static void printUuidNum6(int x,Util &ul); static void printNumUuid7(int x,Util &ul); void mt8(int x,int y,Util &ul); }; #endif //Model//Util.cpp #include "Model/Util.h" int Util::num = 0; char *Util::dtValue = (char *)malloc(20); char *Util::uuidValue = (char *)malloc(40); Util::Util() { cout << ++num << ",In constructor!" << endl; } Util::~Util() { cout << --num << ",In deconstructor!" << endl; } void Util::mt8(int x,int y,Util &ul) { thread t1(printUuidNum6,x,std::ref(ul)); t1.join(); thread t2(printNumUuid7,y,std::ref(ul)); t2.join(); cout<<getTimeNow()<<", finished in void Util::mt8(int x,int y,Util &ul)!"<<endl; } void Util::printNumUuid7(int x,Util &ul) { for(int i=0;i<x;i++) { cout<<i<<","<<ul.getUuid()<<endl; } } void Util::printUuidNum6(int x,Util &ul) { for(int i=0;i<x;i++) { cout<<ul.getUuid()<<","<<i<<endl; } } char *Util::getUuid() { uuid_t newUUID; uuid_generate(newUUID); uuid_unparse(newUUID, uuidValue); return uuidValue; } char *Util::getTimeNow() { time_t rawTime = time(NULL); struct tm tmInfo = *localtime(&rawTime); strftime(dtValue, 20, "%Y%m%d%H%M%S", &tmInfo); return dtValue; } //main.cpp #include "Model/Util.h" using namespace std; void mt3(int x,int y); int main(int args, char **argv) { mt3(atoi(argv[1]), atoi(argv[2])); } void mt3(int x,int y) { Util ul; ul.mt8(x,y,std::ref(ul)); }
Compile
g++ -g -std=c++2a -I. *.cpp ./Model/*.cpp -o h1 -luuid -lpthread;
Run
time ./h1 10 10;
As the above snapshot illustrates that when I pass reference type in thread,it will only invoke deconstructor once.