在 C++ 中使用 RAII 在线程包装器 class 中移动语义
move sematics in thread wrapper class with RAII in C++
我正在尝试让 RAII 包装器 class 围绕 std::thread 在 C++ 中工作。
#include <iostream>
#include <thread>
#include <vector>
using std::cout;
using std::endl;
void threadFunction()
{
for (int i = 0; i < 20; ++i) {
cout << "thread function pointer executing..." << i << endl;
}
}
// RAII wrapper that supports automatic join
class ThreadJoinRAII
{
std::thread thread_;
public:
ThreadJoinRAII(std::thread&& t):thread_(std::move(t))
// ThreadJoinRAII()
{
cout << "ThreadJoinRAII ctor" << endl;
}
//ThreadJoinRAII(const ThreadJoinRAII& other) = delete;
//ThreadJoinRAII& operator=(const ThreadJoinRAII& other) = delete;
//ThreadJoinRAII(ThreadJoinRAII&& other):thread_(std::move(other.thread_))
//{
// cout << "ThreadJoinRAII move ctor" << endl;
//}
//ThreadJoinRAII& operator=(ThreadJoinRAII&& other)
//{
// cout << "ThreadJoinRAII move op" << endl;
// thread_ = std::move(other.thread_);
// return *this;
//}
~ThreadJoinRAII()
{
cout << "in ThreadJoinRAII dtor" << endl;
if (thread_.joinable()) {
thread_.join();
cout << "join thread id = " << thread_.get_id() << endl;
} else {
cout << "thread not joinable. id=" << thread_.get_id() << endl;
}
}
};
class Something
{
std::vector<int> vec_;
public:
Something(std::vector<int>&& v):vec_(std::move(v)) {
cout << "Something ctor" << endl;
}
};
void testRAII()
{
ThreadJoinRAII t1(std::move(std::thread(threadFunction))); // prints ThreadJoinRAII ctor
ThreadJoinRAII t2(std::thread(threadFunction)); // prints nothing
Something s1(std::vector<int>(3, 4)); // prints Something ctor
}
int main(int argc, char* argv[])
{
testRAII();
return 0;
}
问题是 testRAII()
中的 t2
行没有打印任何内容。那部分我不明白。我尝试 add/remove 复制操作和移动操作,但它们没有任何区别。
我的问题是:
-
std::thread(threadFunction)
不是已经是 testRAII()
中的右值了吗?为什么我必须移动它才能使构造函数工作?
- 如果未使用提供的构造函数,
t2
会调用什么代码?我没有看到打印的 ThreadJoinRAII ctor。
s1
行打印出“Something ctor”。 t2
和 s1
有什么区别? std::thread
右值是否被区别对待?
顺便说一句,我在 Ubuntu 20.04 LTS 上用 g++ 9.3 和 g++ -std=c++17 -o mt mt.m.cpp -lpthread
编译了代码。 mt.m.cpp
是我的文件名。
乍一看可能不像,但t2
是函数原型,不是变量声明(搜索“最烦人的解析”)。
您可以通过添加一些括号将其更改为变量:
ThreadJoinRAII t2((std::thread(threadFunction)));
然后它将调用您的 ThreadJoinRAII
构造函数。
我正在尝试让 RAII 包装器 class 围绕 std::thread 在 C++ 中工作。
#include <iostream>
#include <thread>
#include <vector>
using std::cout;
using std::endl;
void threadFunction()
{
for (int i = 0; i < 20; ++i) {
cout << "thread function pointer executing..." << i << endl;
}
}
// RAII wrapper that supports automatic join
class ThreadJoinRAII
{
std::thread thread_;
public:
ThreadJoinRAII(std::thread&& t):thread_(std::move(t))
// ThreadJoinRAII()
{
cout << "ThreadJoinRAII ctor" << endl;
}
//ThreadJoinRAII(const ThreadJoinRAII& other) = delete;
//ThreadJoinRAII& operator=(const ThreadJoinRAII& other) = delete;
//ThreadJoinRAII(ThreadJoinRAII&& other):thread_(std::move(other.thread_))
//{
// cout << "ThreadJoinRAII move ctor" << endl;
//}
//ThreadJoinRAII& operator=(ThreadJoinRAII&& other)
//{
// cout << "ThreadJoinRAII move op" << endl;
// thread_ = std::move(other.thread_);
// return *this;
//}
~ThreadJoinRAII()
{
cout << "in ThreadJoinRAII dtor" << endl;
if (thread_.joinable()) {
thread_.join();
cout << "join thread id = " << thread_.get_id() << endl;
} else {
cout << "thread not joinable. id=" << thread_.get_id() << endl;
}
}
};
class Something
{
std::vector<int> vec_;
public:
Something(std::vector<int>&& v):vec_(std::move(v)) {
cout << "Something ctor" << endl;
}
};
void testRAII()
{
ThreadJoinRAII t1(std::move(std::thread(threadFunction))); // prints ThreadJoinRAII ctor
ThreadJoinRAII t2(std::thread(threadFunction)); // prints nothing
Something s1(std::vector<int>(3, 4)); // prints Something ctor
}
int main(int argc, char* argv[])
{
testRAII();
return 0;
}
问题是 testRAII()
中的 t2
行没有打印任何内容。那部分我不明白。我尝试 add/remove 复制操作和移动操作,但它们没有任何区别。
我的问题是:
-
std::thread(threadFunction)
不是已经是testRAII()
中的右值了吗?为什么我必须移动它才能使构造函数工作? - 如果未使用提供的构造函数,
t2
会调用什么代码?我没有看到打印的 ThreadJoinRAII ctor。 s1
行打印出“Something ctor”。t2
和s1
有什么区别?std::thread
右值是否被区别对待?
顺便说一句,我在 Ubuntu 20.04 LTS 上用 g++ 9.3 和 g++ -std=c++17 -o mt mt.m.cpp -lpthread
编译了代码。 mt.m.cpp
是我的文件名。
乍一看可能不像,但t2
是函数原型,不是变量声明(搜索“最烦人的解析”)。
您可以通过添加一些括号将其更改为变量:
ThreadJoinRAII t2((std::thread(threadFunction)));
然后它将调用您的 ThreadJoinRAII
构造函数。