C_and_CPP 板


LINE

个人学习速度慢, 2016 了才学到 2011 的东西。 有个很仔细的版本, 我这篇不那麽长。 之前稍微接触过 c++ 11 move semantic, 那时候似懂非懂不是很清楚这是干嘛的, 我一开 始还把 move semantic 和 return value optimization 搞混了, return value optimization 并不需要 move semantic 才能做到。 再看过 rust 的 move semantic 之後, 才知道这东西的应用, rust 逼开发人员要搞懂这 个, 不是坏事, 但我喜欢 c++, 让我们从 c++ 来理解这个概念。 为了支援 move semantic, c++ 11 引入了 rvalue reference, 写成 &&, ex: int &&ri, ri 就是一个 rvalue reference type。 所以 ctor 又多了一个 rvalue 的版本 (ref L28); 当然 operator= 也是, 创造一个 class 要愈写愈多程式码。 rust 的这个概念是为了记忆体安全性, c++ 则是为了性能。简单来说就是希望一个 object 不需要作 copy 的动作。什麽叫作「不需要作 copy 的动作」? 你可能需要自己写一个类似 std::string (这是一个练习写 class 的好方法) 的 class 才能理解 move semantic, 我刚好有一个现成的, 拿来理解这样的行为正好, 顺便支援 move semantic。DS::string 就是我的模仿品, 里头有个 char *str_, 复制一个 DS::string 需要连 str_ 一起复制, 若是用 move 则是把原本的 s1::str_ 转到 s2::str_, 那你一定会问:「转过去了, s1::str_ 剩下什麽? 什麽又是《转过去》?」答 案是你给他什麽就是什麽了。一般会给他 nullptr, 免得解构函式发动时出问题, 因为解 构函式会执行 delete [] str_, 我是给 0。这就是为什麽 move 後原来的 s1::str_ 不 能用, 不过 c++ compiler 可不像 rust 会帮你挡下来, 我在这个范例上还是照用, 结果 就是预期的 null pointer。 复制为什麽比较慢, 看以下的程式码行为应该就可以理解了: 复制: strcpy(s2::str_, s1:str_) move : s2::str_ = s1:str_ 比较奇怪的是 L118 若改成 void f3(DS::string &&s) 反而不会发动 move ctor, 这里 我不是很理解。 ANS 这个在我反组译之後有了新的理解, 类似传 reference (pointer), 根本不会发动 (也用 不着) 任何 ctor。 L141 std::move 就是来把这个 object 变成 rvalue, 用 f3((DS::string &&)(s1)); 也 可以, 这样才能发动 move ctor, L28 那个有两个 && 就是 move ctor; 否则只会发动 copy ctor, 这就没有节省执行时间了。 mystring.cpp 1 #include "mystring.h" 2 #include "myiostream.h" 3 #include "mem.h" 4 5 #ifdef TEST 6 #include <cstdio> 7 using namespace std; 8 #else 9 // #define std DS 10 #endif 11 12 DS::string::string():len_(0), str_(0) 13 { 14 #ifdef TEST 15 std::printf("1 ctor\n"); 16 #endif 17 } 18 19 DS::string::string(const char *str) 20 { 21 generate_string(str, s_strlen(str)); 22 23 #ifdef TEST 24 std::printf("const char *str ctor\n"); 25 #endif 26 } 27 28 DS::string::string(string &&s) 29 { 30 str_ = s.str_; 31 len_ = s.len_; 32 s.str_ = 0; 33 s.len_ = 0; 34 #ifdef TEST 35 std::printf("move ctor\n"); 36 #endif 37 } 38 39 DS::string::string(const string &s) 40 { 41 generate_string(s.c_str(), s.length()); 42 43 #ifdef TEST 44 std::printf("copy ctor\n"); 45 #endif 46 } 47 48 DS::string::~string() 49 { 50 #ifdef TEST 51 std::printf("11 dtor:%s\n", str_); 52 #endif 53 delete [] str_; 54 //cout << "string ~ctor" << endl; 55 } 56 113 114 #ifdef TEST 115 #include <stdio.h> 116 #include <utility> 117 118 void f3(DS::string s) 119 { 120 printf("f3 s: %s\n", s.c_str()); 121 } 122 123 DS::string f2() 124 { 125 DS::string s1{"f2"}; 126 return s1; 127 } 128 129 DS::string f1() 130 { 131 std::printf("bb\n"); 132 DS::string s1{"return str"}; 133 std::printf("ee\n"); 134 return s1; 135 } 136 137 int main(int argc, char *argv[]) 138 { 139 DS::string s1=f2(); 140 printf("s1: %s\n", s1.c_str()); 141 f3(std::move(s1)); 142 printf("s1: %s\n", s1.c_str()); 143 printf("s1.length(): %d\n", s1.length()); 144 183 return 0; 184 } 185 #endif list 1. 执行结果 1 const char *str ctor 2 s1: f2 3 move ctor 4 f3 s: f2 5 11 dtor:f2 6 s1: (null) 7 s1.length(): 0 8 11 dtor:(null) rust 预设行为是 move semantic, 我不知道这是不是好事情, 不过和 c++ move semantic 一样, 都需要一点点的专业知识才能理解, 这是他们的高门槛。 最後想问, 大费周张搞了个 move semantic 可以用在哪些地方? 毕竟宣告了一个 object, 几乎都会在继续使用, 如果传给一个 function 後就不能用了, 那写起来会很不 习惯, rust 就是这样, 容器是一个很好的应用, 把 object 放进容器之後, 就可以用容 器的 object, 并不在需要用这个 object 来操作, 所以放进容器的 object 就很适合 move semantic。另外有个网友补充了两点, 感谢。 下面的参考连结写的不错, 不过我有自信你能看懂这篇的话, 应该不需要看以下两个连结 , 但是其提供的《c++ copy and swap idiom 用法 ( https://goo.gl/NU7HmE )》让我非 常受用。 ref: 翻:怎理解 C++ 11中的move(基)--- An answer from stackoverflow ( http://goo.gl/jElp2n ) 翻:怎理解 C++ 11中的move(深入)--- An answer from stackoverflow ( http://goo.gl/wdV2Ot ) // 本文使用 Blog2BBS 自动将Blog文章转成缩址的BBS纯文字 http://goo.gl/TZ4E17 // blog 版本 http://descent-incoming.blogspot.tw/2016/05/c-11-move-semantic.html -- 纸上得来终觉浅,绝知此事要躬行。 --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 1.200.59.8
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1465141530.A.911.html ※ 编辑: descent (1.200.59.8), 06/05/2016 23:46:17
1F:→ chiwa: rvalue 不等於 rvalue reference 06/06 20:10
感谢提醒
2F:推 Dannvix: 延伸阅读Scott Meyers on Uni. Ref. http://j.mp/1su76iV 06/06 20:17
※ 编辑: descent (223.142.207.206), 06/09/2016 16:39:11







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Tech_Job站内搜寻

TOP