据我所知,调用构造函数/析构函数的方式唯一不同取决于实例化顺序。但是“标准”用户类和std中的类之间是否有任何其他区别?
假设我有一个名为myStackOverflow
的类,然后我实例化了这个类的对象。我在同一范围内也有std::thread
类型的对象。这些对象的构造函数或析构函数的调用方式是否存在差异?
我问这个问题的主要原因是根据C++ standard(第30.3.2.3节)join()
未在线程析构函数中调用。您可以阅读here的原因。但是在关于stackoverflow的this回答中,提到将std::thread
包装在另一个类中,然后在这个新包装类的析构函数中调用join()
。我不明白这将如何解决任何问题。析构函数仍然是析构函数,在join()
的析构函数中调用std::thread
的危险仍然存在。
唯一有意义的方法是调用这两种不同类型的析构函数的方式不同。
答案 0 :(得分:0)
好的@Ali,让我们简单概述一些事情(条款)。
namespace std
- 是一个简单的命名空间,如:
namespace my_namespace {
int my_integer;
};
其中包含大量有用的程序员类,由超级强大的程序员编写,并且,正如您所理解的那样,它应该尽可能灵活(后面的“声明1”),不同的人有不同的需求。
当然它遵循c ++标准的一般规则,因为它的内容也是如此。
现在让我们谈谈您想要的std::thread
。
它是一个代表a single thread of execution的简单类。它允许您在“外太空”中执行您的功能,并与我们的抽象“外太空”保持联系,它还处理一些数据:
如果您查看some references更多详细信息并牢记我们的“声明1”,您会注意到以下信息:
std::thread
个对象也可能处于不代表任何线程的状态”std::thread
对象可能代表相同的执行线程; std::thread
不是CopyConstructible或CopyAssignable,尽管它是MoveConstructible和MoveAssignable。”现在您应该得出结论std::thread
变量和执行实体是分开的,但是尝试删除附加到执行实体的std::thread
变量会引发异常。
但是当实体完成执行时,std::thread
变量保持活动状态,并且可以附加到任何其他实体。
对于需要有以下方法:
join() // waits for a thread to finish its execution
// if it is attached to something, the code execution will not go futher until our entity finishes its execution.
detach() // permits the thread to execute independently from the thread handle
// detaches our std:: thread variable from executing entity, now our entity lives its own life. std::thread variable may be removed while the entity keeps alive
joinable() // checks whether the thread is joinable, i.e. potentially running in parallel context
// if thread is attached to something which is executing now, it returns true, otherwise false
这里有一些代码示例可以清除你的误解:
#include <iostream>
#include <thread>
#include <chrono>
using namespace::std;
void some_func1() {
cout << "some_func1 thread started " << endl;
this_thread::sleep_for(chrono::seconds(2));
cout << "some_func1 thread finished " << endl;
}
void some_func2() {
cout << "some_func2 thread started " << endl;
this_thread::sleep_for(chrono::seconds(2));
cout << "some_func2 thread finished " << endl;
}
int main() {
thread some_thread;
cout << "Is some_thread joinable: " << some_thread.joinable() << endl;
some_thread = thread(some_func1);
cout << "Is some_thread joinable: " << some_thread.joinable() << endl;
some_thread.detach();
cout << "Is some_thread joinable: " << some_thread.joinable() << endl;
this_thread::sleep_for(chrono::seconds(1));
some_thread = thread(some_func2);
cout << "Is some_thread joinable: " << some_thread.joinable() << endl;
some_thread.join();
cout << "Is some_thread joinable: " << some_thread.joinable() << endl;
}
// Output is:
// Is some_thread joinable: 0
// some_func1 thread started
// Is some_thread joinable: 1
// Is some_thread joinable: 0
// some_func2 thread started
// Is some_thread joinable: 1
// some_func1 thread finished
// some_func2 thread finished
// Is some_thread joinable: 0
// Press any key to continue . . .
如果你想确保你的实体在线程变量移除之前完成执行,你可以将它包装在另一个类中,并在析构函数中调用join()
,如你所提到的那样。
或者您也可以将其包装在另一个将在析构函数中调用detach()
的文件中。
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
typedef void Myfunc();
void some_func1() {
cout << "some_func1 thread started " << endl;
this_thread::sleep_for(chrono::seconds(2));
cout << "some_func1 thread finished " << endl;
}
void some_func2() {
cout << "some_func2 thread started " << endl;
this_thread::sleep_for(chrono::seconds(2));
cout << "some_func2 thread finished " << endl;
}
class ICareAboutThread {
std::thread thread_;
public:
ICareAboutThread( Myfunc f = nullptr) : thread_(f) {};
~ICareAboutThread() { join(); }
bool joinable() { return thread_.joinable();}
void join() { thread_.join();}
void detach() { thread_.detach();}
// other constructors : move , safe copying - if necessary;
};
class IDontCareAboutThread {
std::thread thread_;
public:
IDontCareAboutThread(Myfunc f = nullptr) : thread_(f) {};
~IDontCareAboutThread() { detach(); }
bool joinable() { return thread_.joinable(); }
void join() { thread_.join(); }
void detach() { thread_.detach(); }
// other constructors : move , safe copying - if necessary;
};
int main() {
ICareAboutThread i_care(some_func1);
this_thread::sleep_for(chrono::seconds(1));
IDontCareAboutThread i_dont_care(some_func2);
return 0;
}
// Output is:
// some_func1 thread started
// some_func2 thread started
// some_func1 thread finished
// Press any key to continue . . .
现在我希望它清楚地告诉你,如果你理解变量何时删除:D