C_and_CPP 板


LINE

※ 引述《Keitaro (动き出す时间...)》之铭言: : 开发平台(Platform): (Ex: Win10, Linux, ...) : Ubuntu 18.04 LTS : 编译器(Ex: GCC, clang, VC++...)+目标环境(跟开发平台不同的话需列出) : gcc : 程式码(Code):(请善用置底文网页, 记得排版,禁止使用图档) : https://ideone.com/jugcYC : 重新上传完整原始码 後面恕删, 因为看起来不像 C++ 所以路过分享一下拙见. C++ 物件不仅仅是一块记忆体, 因为生命周期中会有建构子/解构子参与, 简单 说就是至少会比 C 语言多两次函式呼叫. 所以撰写的时候不会轻易地创造物件 , 更不会创完而不用它. array new/delete 这种昂贵的操作其实是蛮罕见的. 你的程式码主要存在两个问题: 1. ParseCmd() 的实作没有弹性, 且效率不高 2. 准备 execve() 引数时做了许多不必要的操作 一般为了减少对 STL container 的依赖, 函式介面会倾向於接受迭代器而不是 特定容器型别物件, 而且除非你很确定要用 std::char_traits<CharT>::eq() 来比较字元是否相等, 不然我们在搜寻的时候倾向於呼叫 STL algorithm 而非 std::basic_string 这种内嵌比较逻辑的型别, 所以通常介面会这样设计: template <typename ForwardIterator, typename ForwardSentinel, typename OutputIterator> void ParseCmd(ForwardIterator first, ForwardSentinel last, OutputIterator output) { while (first != last) { // call std::find() here // other code goes here (*output++) = std::string(first, last); } } #include <iterator> const std::string str = "-vsync 0 -i file.cfg Compare.yuv"; std::vector<std::string> vCmdSet; ParseCmd(begin(str), end(str), std::back_inserter(vCmdSet)); std::basic_string 只作为字元的载体, 而不是兼做比较的角色. 再来是准备 execve() 引数的逻辑, 如果非得用 array new/delete 来管理物 件, 那前面呼叫 ParseCmd() 创建一堆 std::string 物件有什麽用呢? 有没 有办法重复使用这些物件的内容呢? 实际上你可以呼叫 std::string::data() 成员函式来达成这件事情, 然後把拿到的指标存进另一个 std::vector 内: #include <algorithm> #include <iterator> std::vector<char*> ppCmdArg; std::transform(begin(vCmdSet), end(vCmdSet), std::back_inserter(ppCmdArg), [](std::string& s) { return data(s); }); ppCmdArg.push_back(nullptr); execve(..., data(ppCmdArg), ...); 这里用到的概念主要有两个: 1) std::vector 的 data() 成员函式会回传第 0 个元素的位址, 而且每个成员的位址保证是连续的, 所以回传的东西和你用 array new 创建出来的 array of pointers 是相同的; 2) 再者 std::string 的 data() 成员函式会回传第 0 个字元的位址, 每个字元的位址也是连续的, 而且回传的记忆体和 c_str() 相同 (只差在 constness), 包含结束字元. 下次撰码的时候可以试着写出无 new/delete 的程式码, 因为偏底层的函式呼 叫次数愈多, 发生错误的机会也跟着变多. -- [P1389R1] Standing Document for SG20: Guidelines for Teaching C++ to Beginners https://wg21.link/p1389r1 SG20 Education and Recommended Videos for Teaching C++ https://www.cjdb.com.au/sg20-and-videos --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 123.193.76.216 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1605102909.A.FC2.html
1F:→ Lipraxde: new 的问题是会产生 raw pointer,要主动用 delete 释 11/11 22:28
2F:→ Lipraxde: 放资源。至於昂贵吗...难道 vector、string 就不做 hea 11/11 22:28
3F:→ Lipraxde: p allocation 了? 11/11 22:28
STL container 预设会用 std::allocator<T> 来做配置, 以物件的生命周期来 看, 呼叫的介面先後顺序如下: 1. allocate() 2. construct() 3. destroy() 4. deallocate() 1 ~ 2 的使用效果和 operator new + placement new 相同, 并非使用 array new, 差别在於元素是需要用到的时候才建构, 而非一次全部建构好, 这也是为 什麽如 std::vector 会有 capacity() 及 size() 两种不同用途的成员函式. 说 new 会产生 raw pointer 那不会是什麽太大问题, 因为使用者可以选择重 载 new/delete, 只要在重载版本里做好物件管理即可.
4F:→ CoNsTaR: 还是看使用情景吧,server 可能就会想要一次全部建构好 11/11 23:58
5F:推 Keitaro: 谢谢板上各位先进的指导 11/12 03:48
6F:→ Keitaro: 虽然有很多东西不太了解 我在努力查资料学习 11/12 03:49
7F:→ Keitaro: 让各位花这麽多时间指导小弟 真的非常感谢 11/12 03:50
8F:推 ucrxzero: 是说内文说用s.data()可是代码用data(s)是我看错吗? 11/12 10:10
是的, 你没看错
9F:→ Lipraxde: 我主要是不明白为什麽你文内会写说 new/delete 昂贵( 11/12 22:49
10F:→ Lipraxde: 还是 array 这个字眼在这边很重要?)。 11/12 22:49
你知道 operator new 以及 operator new[] (俗称 array new) 的差异吗? 遇到没有 default constructor 的型别初始化会怎麽进行?
11F:→ Lipraxde: 我怎麽觉得是用法的问题,而不是它本身昂贵? 11/13 01:56
昂贵的原因在於物件的建构方式. 如同阵列般, 元素的建构是彼此相依的, 除了获取记忆体的时间成本; 也额外 付出了第 1 个元素开始建构到第 n - 1 个元素结束建构的时间 (n 为阵列大 小), 我们才能开始存取第 0 个元素. 为了使用 operator new[] 来建构大量物件, 使用者还必须提供成本较低的 default ctor, 让型别支援 two-phase initialization, 也提高程式码复杂度 所以物件分开建构与否直接影响程式的执行效率, 从 C++17 开始新增多种记忆 体管理介面如 std::byte, std::uninitialized_*() 系列函式, 即是为了完善 这部分的开发.
12F:推 Hurricaneger: 看不懂就推 11/13 10:40
13F:→ Lipraxde: 喔~所以说,就是这些多呼叫的 default constructor 造 11/13 11:30
14F:→ Lipraxde: 成它比较贵,感到豁然开朗!我以前基本上都当 default 11/13 11:30
15F:→ Lipraxde: constructor 没什麽成本 Orz 11/13 11:30
如果是 trival default ctor 就不会有什麽成本. 但从 C++11 开始有执行绪的观念; C++17 开始有 executor 平行处理的观念, 在使用 operator new[] 这类操作以前都要思考是否有必要排队循序执行. ※ 编辑: poyenc (61.216.75.43 台湾), 11/13/2020 12:04:52
16F:推 F04E: 这种优文竟然只有三推 11/13 13:03
17F:推 Lipraxde: 谢谢大大的指导 11/13 22:23







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灯, 水草

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

TOP