Re: [问题] 请问char**array的问题

楼主: poyenc (发箍)   2020-11-11 21:55:03
※ 引述《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 的程式码, 因为偏底层的函式呼
叫次数愈多, 发生错误的机会也跟着变多.
作者: Lipraxde (Lipraxde)   2020-11-11 22:28:00
new 的问题是会产生 raw pointer,要主动用 delete 释放资源。至于昂贵吗...难道 vector、string 就不做 heap allocation 了?
作者: CoNsTaR ((const *))   2020-11-11 23:58:00
还是看使用情景吧,server 可能就会想要一次全部建构好
作者: Keitaro (动き出す时间...)   2020-11-12 03:48:00
谢谢板上各位先进的指导虽然有很多东西不太了解 我在努力查资料学习让各位花这么多时间指导小弟 真的非常感谢
作者: ucrxzero (RX-0)   2020-11-12 10:10:00
是说内文说用s.data()可是代码用data(s)是我看错吗?
作者: Lipraxde (Lipraxde)   2020-11-12 22:49:00
我主要是不明白为什么你文内会写说 new/delete 昂贵(还是 array 这个字眼在这边很重要?)。我怎么觉得是用法的问题,而不是它本身昂贵?
作者: Hurricaneger (裤袜脱落大尉)   2020-11-13 10:40:00
看不懂就推
作者: Lipraxde (Lipraxde)   2020-11-13 11:30:00
喔~所以说,就是这些多呼叫的 default constructor 造成它比较贵,感到豁然开朗!我以前基本上都当 defaultconstructor 没什么成本 Orz
作者: F04E (Fujitsu)   2020-11-13 13:03:00
这种优文竟然只有三推
作者: Lipraxde (Lipraxde)   2020-11-13 22:23:00
谢谢大大的指导

Links booklink

Contact Us: admin [ a t ] ucptt.com