免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1601 | 回复: 6
打印 上一主题 下一主题

[C++] 如何理解移动语义"move not usable"的情形? [复制链接]

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:58:11
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-10-09 22:40 |只看该作者 |正序浏览
Scott Meyers的Effective Modern C++第29条款里面谈到:

There are thus several scenarios in which C++11's move semantics do you no good:
第三条的原文是:
Move not usable: The context in which the moving would take place requires a move operation that emits no exceptions, but that operation isn't declared noexcept.

我没有看明白这个条款是什么含义,我理解成: 如果move构造函数里面有抛出异常,那么这个move就不可用----意思move里面throw了异常就是不能编译通过?
可是我在下面的代码也能编译通过啊:

  1. struct S{
  2.     S(){}
  3.     S(S&&)noexcept{throw 1;}
  4. };
  5. int main() {
  6.     try{
  7.     S obj;
  8.     S obj2(move(obj));
  9.     }catch(...){}
  10.     return 0;
  11. }
复制代码
如果noexcept是个君子协定,让编译器不要生成异常处理函数,我可以理解上面的代码,catch不到exception,所以程序异常中止。
但是Scott的这个条款似乎是在说,这样的代码就应该能编译通过?

到底怎么理解呢?

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
7 [报告]
发表于 2015-10-13 08:07 |只看该作者
回复 6# windoze

谢谢!   

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
6 [报告]
发表于 2015-10-12 18:08 |只看该作者
回复 5# bruceteen

标准没规定在这种情况下编译器一定不能用move constructor,也就是说用copy或move constructor都是可以的。
但标准要求在noexcept(true) block里抛出的异常不能被catch,要直接terminate,但这个要求现在的编译器不一定遵从,至少之前某个版本的clang没有。

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
5 [报告]
发表于 2015-10-12 15:09 |只看该作者
回复 4# windoze
请教一下,“但这并不是强制的”是什么意思?
我用gcc4.8.1尝试了一下,调用的是 move构造函数,这是否就是你说的“但这并不是强制的”的诠释?

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
4 [报告]
发表于 2015-10-12 14:31 |只看该作者
不要管有没有throw,编译器不看这个,它只看函数声明里有没有noexcept。

  1. struct S {
  2.     S()=default;
  3.     S(const S&)=default;
  4.     S(S&&s)noexcept(false){...}
  5. };
  6. void f() noexcept(true) {
  7.     // 下面就是个move not usable context,f要求noexcept(true),但S(S&&)是noexcept(false)
  8.     S s(move(some_other_S_instance));
  9. }
复制代码
上面这段代码编译器可以把它编译成用copy construct而不是move construct,因为move constructor不满足noexcept(true)的需求,但这并不是强制的。

论坛徽章:
14
水瓶座
日期:2014-06-10 09:51:0215-16赛季CBA联赛之江苏
日期:2017-11-27 11:42:3515-16赛季CBA联赛之八一
日期:2017-04-12 14:26:2815-16赛季CBA联赛之吉林
日期:2016-08-20 10:43:1215-16赛季CBA联赛之广夏
日期:2016-06-23 09:53:58程序设计版块每日发帖之星
日期:2016-02-11 06:20:00程序设计版块每日发帖之星
日期:2016-02-09 06:20:0015-16赛季CBA联赛之上海
日期:2015-12-25 16:40:3515-16赛季CBA联赛之广夏
日期:2015-12-22 09:39:36程序设计版块每日发帖之星
日期:2015-08-24 06:20:002015亚冠之德黑兰石油
日期:2015-08-07 09:57:302015年辞旧岁徽章
日期:2015-03-03 16:54:15
3 [报告]
发表于 2015-10-10 09:37 |只看该作者
throw是运行期的,跟编译有什么关系勒?编译还能管得了身后事?

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
2 [报告]
发表于 2015-10-10 09:22 |只看该作者
看不懂洋文,我这句话的意思是:某个地方因为种种原因要求不能有异常,但倒霉的是这个move没有声明为noexcept,因此这个地方就不能用这个move了。
更简单的说就是:你不能将一个可能抛出异常的move,用在一个要求不能抛出异常的地方。
这句话看起来是一个人人皆知的废话,但结合上下文,可知作者就是在列举几种不应该用move的场合。
  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP