zzxxisme 最近的时间轴更新
zzxxisme

zzxxisme

V2EX 第 483829 号会员,加入于 2020-04-15 16:03:14 +08:00
zzxxisme 最近回复了
我猜反向执行是在执行 string 和 vector 的析构函数。可以试着回去的时候看看能不能 step in ?
先说我认为的结论:这种写法的主要目的 并不是 为了隐藏实现,而是为了方便转移、复制、释放一个 ModuleBase 子类的对象。

首先我们有 ModuleBase 这个基类,这个基类可能有很多种不同的子类实现,例如 ModuleBaseImpl 是其中一种实现。但是我用这个 Module 的时候我可能不关心具体实现是怎么样,不关心具体的子类是什么。我只想拿到 ModuleBase 的基类的指针(或者引用)进而能够访问子类的具体实现就好了。如果只是这个需求,我的设计可能就是令到 ModuleBase 的虚函数全部都弄成 纯虚函数 (也就是没有默认实现),然后子类 ModuleBaseImpl 必须实现所有纯虚函数。也就是

```c++
class ModuleBase {
...
virtual void startTimer(int32_t timerId, uint64_t msec) = 0; // 纯虚函数
};

class ModuleBaseImpl : public ModuleBase {
...
void startTimer(int32_t timerId, uint64_t msec) override {
... // 具体实现
}
};
```

然后这样会有一个小问题,就是我用一个 Module 的时候,我必须用 ModuleBase 的指针(或者引用,但如果能用引用,可能就没有我说的这个小问题)。而且用这个指针我还要注意适当的时候 delete 这个指针。但是如果这个指针是被其他人用的,在其他人的函数里面他们未必会 delete 这个指针。所以这个时候我需要弄多一个类,来包装这个 ModuleBase 指针,也就是

```c++
class ModuleBaseWrapper {
~ModuleBaseWrapper() { delete module; ​}
private:
​ModuleBase* module;
};

```

有了这个 ModuleBase Wrapper 之后,这个 Wrapper 在析构的时候会帮忙析构这个 ModuleBase 指针。

最后,回到一开始你说的 ModuleBase 里面包含了一个 android::sp<ModuleBase>impl 的事,这个 android::sp<ModuleBase>使得 ModuleBase 可以当做上面的 ModuleBaseWrapper 来用。
@ShikiSuen
> 我重写了逐行处理的版本,倒是成功了。
Congratulation!

0.0 然后有一些小建议。我看你现在的做法是把整个文件读到了内存,我不确定你的文件的大小怎么样,如果文件太大的话,这样其实会占用很多内存,而且本身没有必要一下子把所有行都放到内存再处理。其实你可以在
getline(zfdFormatConsolidatorIncomingStream,zfdBuffer);
拿到一行之后马上就去 regex_replace 你读到的行。另外 regex_replace 的那个地方,其实也没有必要用 c_str(),直接
vecEntry[i] = regex_replace(vecEntry[i], sedWhiteSpace, " ")
反而可能会更好。
@ShikiSuen 我对 C++的 std::regex 真的不熟,它的语法应该是这里提到的 https://en.cppreference.com/w/cpp/regex/ecmascript ,这里面没有提到\h ,所以应该是不支持的。

ObjCpp 和 C++ 是两门不同的语言,ObjCpp 我就完全不懂了…

不过如果可以选择其他语言的话,用自己更擅长的语言会更好 0.0
@ShikiSuen 这样我建议你从文件(也就是档案) zfdFormatConsolidatorIncomingStream 里面一行一行的读进来,每次 regex_replace 处理一行然后输出到新的文件 zfdFormatConsolidatorOutput 。

你可能会问,我能不能改一下 regex 的规则,让它不删除\n 就好了?是可以试着改成"[^\\S\r\n]+",这里\\S 就是所有 非空格字符,\\S\r\n 就是所有非空格加上换行,[^\\S\r\n]就是对“所有非空格字符和换行字符”取反,就变成了“除去换行字符的所有空格字符”。但是这会有一个不好的地方,对于"a \nb",它的替换结果还是"a \nb",而不是“a\nb”,因为这个空格不是 leading 或者 tailing 的空格,所以是被压缩成一个而不是去掉。所以我建议的是读一行处理一行。
@Inn0Vat10n 说的那个 c_str(),只是有点奇怪,但不至于非法。zfdBuffer 它是一个 std::string ,regex_replace 返回的也是一个 std::string ,对 std::string 取 c_str()得到一个 const char*,这样最终就是把一个 const char* 赋值给 std::string ,会把 const char*复制一遍到 std::string 的。我觉得奇怪只是说,c_str()其实是不需要的。

@ShikiSuen 我当初测试用的是这个例子
```c++
std::string zfdBuffer = " \t123 456\t\n789 \taaaa ";
std::cout << '@' << zfdBuffer << '@' << std::endl;
std::regex sedWhiteSpace("\\s+"), sedLeadingSpace("^\\s+"), sedTrailingSpace("\\s+$");
zfdBuffer = std::regex_replace(zfdBuffer, sedWhiteSpace, " ");
zfdBuffer = std::regex_replace(zfdBuffer, sedLeadingSpace, "");
zfdBuffer = std::regex_replace(zfdBuffer, sedTrailingSpace, "");
std::cout << std::endl << '@' << zfdBuffer << '@' << std::endl;
```

它的结果是会把空格,\t ,\n 这些去掉或者合并成一个空格的。所以我觉得原来 regex_replace 的问题应该是解决了的。
```
@ 123 456
789 aaaa @

@123 456 789 [email protected]
```

> 但 Xcode 编译出来之后我发现我这 txt 档案的内容会被清空
我猜可能是其他方面的问题。或者你在第一个 regex_replace 之前把 zdfBuffer 打印出来看是什么内容,然后在最后一个 regex_replace 之后再把 zdfBuffer 打印出来看是什么内容,进行对比?
std::regex 的语法好像比较特别。不太常用不太熟,但是我改成下面的 regex 好像是可以的。

```c++
regex sedWhiteSpace("\\s+"), sedLeadingSpace("^\\s+"), sedTrailingSpace("\\s+$")
```
305 天前
回复了 amiwrong123 创建的主题 C++ std::move 的实现使用到了万能引用?
> 但是我经过了 vs2019 debug 后,发现 c 的类型为 A&&,这是为什么呀?

这个不太清楚怎么回答。我觉得因为你是用 auto&&去接 returnTemp()产生的临时变量,所以 c 的类型就是 A&&。如果你使用 auto 去接,那 c 的类型就是 A 。但我觉得不管 c 的类型是 A&&还是 A ,它都是维持着 A 类对象的一份 local copy ,用起来都是一样。

> _Ty& _Arg 优先级比 _Ty&& _Arg 高

这个我觉得是有条件的。如果参数本身是 A&这样的引用类型,那_Ty& _Arg 有更高的优先级。如果参数是 A 或者 A&&这样的,_Ty&&有更高的优先级。
306 天前
回复了 amiwrong123 创建的主题 C++ std::move 的实现使用到了万能引用?
再插一句,如果你把第二个 fun_test 改成
```
template <class _Ty>
void fun_test(_Ty _Arg) { // 这里把&去掉
cout << "left" << endl;
}
```
那么 fun_test(_Ty&&)和 fun_test(_Ty)在匹配 fun_test(a)的时候,编译器会选不出来而报错,因为这两个函数面对 A&的 rank 一样。
306 天前
回复了 amiwrong123 创建的主题 C++ std::move 的实现使用到了万能引用?
@amiwrong123
> 所以,std::move 只有这一个实现也能正常工作,因为它什么类型都可以接,是吧。附言里我加的这个问题,为什么有了万能引用版本的函数,还能调用到左值引用版本的函数呀?有点不理解了,老哥

这里有两点吧。一个是 _Ty&& 的那个的确能接住所有类型。另一个是,当你还写了一个 _Ty& 版本的函数的情况下,因为 main 函数里面的 fun_test(a)传进去的是 a 的引用,也就是传进去的是 A&,这个情况下,编译器会认为 _Ty& 版本的 fun_test 会比 _Ty&& 版本的 fun_test 有更高的 rank (优先级)去匹配这个 A&。所以正确的说法我觉得是,_Ty&&能够接住所有类型,但是在有其他重载的情况下,_Ty&&不一定有更高的 rank 被用上。你可以看看 https://en.cppreference.com/w/cpp/language/overload_resolution 的 Ranking of implicit conversion sequences 下列举的不同情况。

> 上面这个程序是不是就是你说的意思? constexpr 函数可以赋值给 constexpr 标识符,也可以赋值非常量的标识符(如上程序)
对的。你也可以看看这里最下面给的一些例子: https://en.cppreference.com/w/cpp/language/constexpr
关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3311 人在线   最高记录 5497   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 17ms · UTC 13:27 · PVG 21:27 · LAX 05:27 · JFK 08:27
Developed with CodeLauncher
♥ Do have faith in what you're doing.