移动线程对象后应该把旧线程对象设置成什么呀

z416575462 2017-12-09 12:44:06
我照着书上写了一个scoped_thread类,用来管理线程对象,
每个scoped_thread都存了一个thread对象,用于当程序销毁scoped_thread对象时,
将会在析构函数中调用thread对象的join以便等待线程执行完毕,如下:

#include <thread>
#include <stdexcept>
#include <iostream>
class scoped_thread {
std::thread t;
public:
explicit scoped_thread(std::thread && t_) :t(std::move(t_)) {
if (!t.joinable())
throw std::logic_error("No thread");
}
~scoped_thread() {
t.join();
std::cout << "destruct a thread" << std::endl;
}
scoped_thread(scoped_thread const &) = delete;
scoped_thread& operator=(scoped_thread const &) = delete;
//这下面的是我自己写的,没写完。移动构造器
scoped_thread(scoped_thread && t_) noexcept:t(std::move(t_.t)) { //t_.t = ;不会写了。。
}
//移动赋值运算符,也没写玩,不会写
scoped_thread& operator=(scoped_thread && t_) = default;

};

然后,书上的调用类似这样的:

void funruninthread(){cout<<"hi"<<endl;}
void f(){
scoped_thread st{thread(funruninthread)};
}//这样在函数结束时会自动等待线程执行完毕

,后来,又介绍了把thread对象放入vector中,由此,我就想到了能不能把scoped_thread对象放入vector中呢?
然后我就发现。了一个问题:

vector<scoped_thread> vst;

1,当我往vst中放入scoped_thread对象时,如果vst旧空间不足,会扩容,
然后把容器内的旧空间内的对象挪动到新空间里。然后销毁旧空间。
(就是那个移动构造器和移动赋值运算符那我不会写。。。)
,这样挪动过程好像就会调用scoped_thread对象的析构函数导致线程join,然后新空间中的线程就变成不能join了,这样好像以后真正析构vector容器时就不能再join这个对象了。
如果我写一个移动赋值运算符函数,把一个scoped_thread对象移动给另一个对象后,如何设置旧的scoped_thread对象内的thread成员?让它是一个可以join()的(这样旧的对象也可以析构),但析构又不会影响新scoped_thread的对象呢??
...全文
124 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
z416575462 2017-12-10
  • 打赏
  • 举报
回复
引用 11 楼 hdt 的回复:
[quote=引用 10 楼 z416575462 的回复:] [quote=引用 6 楼 hdt 的回复:] [quote=引用 5 楼 z416575462 的回复:] 如果写成vector<scoped_thread&> vst 那这样好像scoped_thread对象不是由vector统一管理了。感觉好像外面一份,vector内又有个引用。
恰恰相反,vecort<scoped_thread>才是两份。[/quote] 我把拷贝构造器和拷贝赋值运算符都删除了,容器好像不会存两份的。[/quote]删除是不管用的,当你不提供的时候编译器会自动为每个类添加拷贝构造和复制。 你可以把拷贝构造和赋值定义为私有的,就清楚了[/quote] 我是这样删除的:
 
scoped_thread(scoped_thread const &) = delete;
scoped_thread& operator=(scoped_thread const &) = delete;
真相重于对错 2017-12-09
  • 打赏
  • 举报
回复
嗯 存引用确实在生存期控制会有一些问题 那就变成存指针
真相重于对错 2017-12-09
  • 打赏
  • 举报
回复
引用 7 楼 xsklld 的回复:
[quote=引用 2 楼 hdt 的回复:] 试试 vector<scoped_thread&> vst;
容器里存引用要用std::ref包装。[/quote]真的???
真相重于对错 2017-12-09
  • 打赏
  • 举报
回复
引用 10 楼 z416575462 的回复:
[quote=引用 6 楼 hdt 的回复:] [quote=引用 5 楼 z416575462 的回复:] 如果写成vector<scoped_thread&> vst 那这样好像scoped_thread对象不是由vector统一管理了。感觉好像外面一份,vector内又有个引用。
恰恰相反,vecort<scoped_thread>才是两份。[/quote] 我把拷贝构造器和拷贝赋值运算符都删除了,容器好像不会存两份的。[/quote]删除是不管用的,当你不提供的时候编译器会自动为每个类添加拷贝构造和复制。 你可以把拷贝构造和赋值定义为私有的,就清楚了
z416575462 2017-12-09
  • 打赏
  • 举报
回复
引用 6 楼 hdt 的回复:
[quote=引用 5 楼 z416575462 的回复:] 如果写成vector<scoped_thread&> vst 那这样好像scoped_thread对象不是由vector统一管理了。感觉好像外面一份,vector内又有个引用。
恰恰相反,vecort<scoped_thread>才是两份。[/quote] 我把拷贝构造器和拷贝赋值运算符都删除了,容器好像不会存两份的。
z416575462 2017-12-09
  • 打赏
  • 举报
回复
我自己想了个办法:增加一个bool成员。 在析构的时候判断一下,如果为真才join, 而在移动构造器里,移动后把旧对象的该成员设置为假。 就好了
xskxzr 2017-12-09
  • 打赏
  • 举报
回复
引用 2 楼 hdt 的回复:
试试 vector<scoped_thread&> vst;
容器里存引用要用std::ref包装。
真相重于对错 2017-12-09
  • 打赏
  • 举报
回复
引用 5 楼 z416575462 的回复:
如果写成vector<scoped_thread&> vst 那这样好像scoped_thread对象不是由vector统一管理了。感觉好像外面一份,vector内又有个引用。
恰恰相反,vecort<scoped_thread>才是两份。
z416575462 2017-12-09
  • 打赏
  • 举报
回复
如果写成vector<scoped_thread&> vst 那这样好像scoped_thread对象不是由vector统一管理了。感觉好像外面一份,vector内又有个引用。
z416575462 2017-12-09
  • 打赏
  • 举报
回复
可是我并不希望在容器扩容的时候等待容器中的所有线程啊。 我只是希望容器扩容归扩容, 而等待所有线程都放到容器销毁的那一刻才等待线程。
真相重于对错 2017-12-09
  • 打赏
  • 举报
回复
你这么想。 比如你邀请了一堆富翁,比如马云,王建玲都来了 可以把一间房子,想成vector, 让马云他们都尽了这间房子,那么这间房子之外,还会有马云他们吗? 当然,也可能有个邪恶的科学家,发明了复制机器,临时复制了一堆小马云。。。。等他们一进入那间房子,立刻用假的夺了他们的财产。 当然以上,都是我模仿某个低劣的科幻小说的瞎想
真相重于对错 2017-12-09
  • 打赏
  • 举报
回复
试试 vector<scoped_thread&> vst;
xskxzr 2017-12-09
  • 打赏
  • 举报
回复
把t.join()包一层try catch就行了。 如果t被移动过,标准保证执行t.join()会抛system_error。可以参考这个例子
Google Android SDK开发范例大全(完整版)共4个分卷 目录 第1章 了解.深入.动手做. 1.1 红透半边天的Android 1.2 本书目的及涵盖范例范围 1.3 如何阅读本书 1.4 使用本书范例 1.5 参考网站 第2章 Android初体验 2.1 安装AndroidSDK与ADTplug-in 2.2 建立第一个Android项目(HelloAndroid!) 2.3 Android应用程序架构——从此开始 2.4 可视化的界面开发工具 2.5 部署应用程序到Android手机 第3章 用户人机界面 3.1 更改与显示文字标签——TextView标签的使用 3.2 更改手机窗口画面底色——drawable定义颜色常数的方法 3.3 更改TextView文字颜色——引用Drawable颜色常数及背景色 3.4 置换TextView文字——CharSequence数据类型与ResourceID应用 3.5 取得手机屏幕大小——DisplayMetrics取得画面宽高的方法 3.6 样式化的定型对象——Style样式的定义 3.7 简易的按钮事件——Button事件处理 3.8 手机页面的转换——setContentView的应用 3.9 调用另一个Activity——Intent对象的使用 3.10 不同Activity之间的数据传递——Bundle对象的实现 3.11 返回数据到前一个Activity——startActivityForResult方法 3.12 具有交互功能的对话框——AlertDialog窗口 3.13 置换文字颜色的机关——Button与TextView的交互 3.14 控制不同的文字字体——Typeface对象使用 3.15 如iPhone拖动相片特效——Gallery画廊 3.16 自制计算器——多按钮的整合应用 3.17 关于(About)程序信息——Menu功能菜单程序设计 3.18 程序加载中,请稍后——ProgressDialog与线程整合应用 3.19 全屏幕以按钮覆盖——动态产生按钮并最大化 3.20 今晚到哪儿打牙祭?——具选择功能的对话框 3.21 Android变脸——主题(Theme)实现 第4章 史上超豪华的手机控件 4.1 EditText与TextView共舞——setOnKeyListener事件 4.2 设计具有背景图的按钮——ImageButton的焦点及事件处理 4.3 给耶诞老人的信息——Toast对象的使用 4.4 我同意条款——CheckBox的isChecked属性 4.5 消费券采购列表——多选项CheckBox的应用 4.6 向左或向右——RadioGroup组与onCheckedChanged事件 4.7 专业相框设计——ImageView的堆栈应用 4.8 自定义下拉菜单模式——Spinner与setDropDownViewResource 4.9 动态添加/删除的Spinner菜单——ArrayList与Widget的依赖性 4.10 心爱小宝贝相片集——Gallery与衍生BaseAdapter容器 4.11 快速的搜索手机文件引擎——JavaI/O的应用 4.12 按钮也能随点击变换——ImageButton选择特效 4.13 具自动提示功能的菜单——AutoCompleteTextView与数组 4.14 数字及模拟小时钟设计——AnalogClock与DigitalClock的原理 4.15 动态输入日期与时间——DatePicker与TimePicker应用 4.16 猜猜红心A在那儿——ImageView点击事件与透明度处理 4.17 后台程序运行进度提示——ProgressBar与Handler的整合应用 4.18 动态文字排版——GridView与ArrayAdapter设计 4.19 在Activity里显示列表列表——ListView的布局 4.20 以动态列表配置选项——ListActivity与Menu整合技巧 4.21 查找程序根目录下所有文件——JavaI/O与ListActivity的结合.. 4.22 加载手机磁盘里的图文件——使用decodeFile方法 4.23 动态放大缩小ImageView里的图片——运用Matrix对象来缩放图文件 4.24 动态旋转图片——Bitmap与Matrix旋转ImageView 4.25 猜猜我在想什么——RadioButtonID 4.26 离开与关闭程序的弹出窗口——对话窗口上的ICON图标 第5章 交互式通信服务与手机控制 5.1 具有正则表达式的TextView——Linkify规则 5.2 ACTION!CALL!拨打电话——Intent

64,651

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧