c++ unique_ptr系列和rust的所有权差不多的; 至少在新项目中严格遵循RAII, 不会存在问题的;
rust: 边界检查, &是指针等等限制总是要绕, 解引用, unsafe...;
pub fn upper(str: &mut String){
unsafe {
let chars = str.as_mut_vec();
for c in chars {
if *c as u8 <= 'z' && *c as u8 >= 'a'{
*c = *c - 32;
}
}
}
}
unsafe {
map.get_unchecked(0)
}
if let val = map.get(0)
map.get(0).unwarp()...
C++
// 大写
void upper(string &str){
for(char & i : str){
if (i <= 'z' && 'a' <= i) {
i -= 32;
}
}
}
map[0]
map[0] == NULL
1
共 10 条评论, 1 页
评论区
写评论我只能认为或许优化的时候会把这几次位运算全都优化掉,所以一直懒得改吧?但无论如何,直接一次运算一次判断明显更容易懂,维护起来也更方便些吧?
你这个应该是1.52改的,还没release。
我的1.51版本是,先转化为U8,然后转化为小写字母的U8,然后转为char。其中小写大写U8的转化是两次的位运算。还需要判断一次是否是小写。
反过来,转为大写是三次位运算和一次判断。
估计1.52会一起改了吧。本来这个就有点奇怪,明明可以一次判断一次运算完成,硬要一次判断两/三次位运算完成。
--
👇
johnmave126: 我又查了一下标准库是一次判断,一次位运算啊
to_ascii_lowercase
ascii_change_case_unchecked
--
👇
eweca-d: 首先这里没有边界检查吧?如果你指的是检查小写字母边界的话,在rust里,使用的是
b'a'
这种形式就可以转化为ascii值了(u8)。另外吐槽下,根据C++反推,你的rust的upper和lower函数的ascii写反了。解引用总要绕,这个不用绕属于语法糖范畴了吧。还可以吐槽C++解引用式使用变量需要
->
而rust有自动deref
呢。unsafe是特性。你既然想做危险操作,那就要unsafe。
查了下标准库,我比较好奇的是,标准库为什么使用
*self & !((self.is_ascii_lowercase() as u8) << 5)
来转化为大写?不过是一次判断,一次减法解决的问题,为什么要一次判断,三次位运算?我又查了一下标准库是一次判断,一次位运算啊
to_ascii_lowercase
ascii_change_case_unchecked
--
👇
eweca-d: 首先这里没有边界检查吧?如果你指的是检查小写字母边界的话,在rust里,使用的是
b'a'
这种形式就可以转化为ascii值了(u8)。另外吐槽下,根据C++反推,你的rust的upper和lower函数的ascii写反了。解引用总要绕,这个不用绕属于语法糖范畴了吧。还可以吐槽C++解引用式使用变量需要
->
而rust有自动deref
呢。unsafe是特性。你既然想做危险操作,那就要unsafe。
查了下标准库,我比较好奇的是,标准库为什么使用
*self & !((self.is_ascii_lowercase() as u8) << 5)
来转化为大写?不过是一次判断,一次减法解决的问题,为什么要一次判断,三次位运算?这个标准库实现确实有点怪怪的,掏出godbolt看了一下也确实是直接判断指令数又少又简单。
我盲猜一个是为了在低优化级别下减少分支数?
--
👇
eweca-d: 首先这里没有边界检查吧?如果你指的是检查小写字母边界的话,在rust里,使用的是
b'a'
这种形式就可以转化为ascii值了(u8)。另外吐槽下,根据C++反推,你的rust的upper和lower函数的ascii写反了。解引用总要绕,这个不用绕属于语法糖范畴了吧。还可以吐槽C++解引用式使用变量需要
->
而rust有自动deref
呢。unsafe是特性。你既然想做危险操作,那就要unsafe。
查了下标准库,我比较好奇的是,标准库为什么使用
*self & !((self.is_ascii_lowercase() as u8) << 5)
来转化为大写?不过是一次判断,一次减法解决的问题,为什么要一次判断,三次位运算?首先这里没有边界检查吧?如果你指的是检查小写字母边界的话,在rust里,使用的是
b'a'
这种形式就可以转化为ascii值了(u8)。另外吐槽下,根据C++反推,你的rust的upper和lower函数的ascii写反了。解引用总要绕,这个不用绕属于语法糖范畴了吧。还可以吐槽C++解引用式使用变量需要
->
而rust有自动deref
呢。unsafe是特性。你既然想做危险操作,那就要unsafe。
查了下标准库,我比较好奇的是,标准库为什么使用
*self & !((self.is_ascii_lowercase() as u8) << 5)
来转化为大写?不过是一次判断,一次减法解决的问题,为什么要一次判断,三次位运算?你这个例子确实是特殊情况,因为是string所以才要unsafe才能去按字节改,如果参数是vec肯定是没这问题的。毕竟这两个东西在Rust里完全是天差地别,另外Rust里还有path、osstr、cstring这些在c++里都可以用string表示的东西,确实看起来搞的很复杂,只不过这些在C++里语言本身没有要求你注意而已。像windows用gbk,linux用utf8,你的代码在移植的时候由于os的编码不同导致错误,以及path一个正斜杠一个反斜杠等等,这也确实是存在的问题。C++的做法是你自己保证,Rust的做法是我强制你处理这些问题,所以显得麻烦,但也不是没有道理。
--
👇
Aya0wind: 转大小写没有问题,但是其他操作就不一定了,毕竟你按字节修改了string,就没法保证string还是正确的utf8格式了。否则就失去了区分safe代码和unsafe代码的意义了,除非把string你转vec去改,改完再用from_utf8重新验证一下正确性,这样也是safe的。如果你知道你的unsafe操作是绝对没问题的,那么就可以把unsafe封装成safe。
👇
sstudioer: // 这个中文也没问题的, utf8若是多字节首位必是b1xx0_0000 > 'z'; 我只是举个例子;
--
👇
Aya0wind: 你这例子举的不好。 Rust的String是一个utf8字符串,一个字符不是固定1字节的,你要按字节修改本来就会有破坏utf8字符串结构的可能,而C++的string就是一个bytearray,根本没规定编码,是一字节一字节访问的,本来就不一样。 Rust因为要保证不出问题才让你以字节修改字符串为unsafe操作的。你这段C++代码,要是string里面来几个中文字符,这么一操作,整个字符串就要乱了,后面再按utf8规则去使用,搞不好就要出错甚至直接导致程序崩掉,只是无视了问题,而不是解决了问题罢了。
转大小写没有问题,但是其他操作就不一定了,毕竟你按字节修改了string,就没法保证string还是正确的utf8格式了。否则就失去了区分safe代码和unsafe代码的意义了,除非把string你转vec去改,改完再用from_utf8重新验证一下正确性,这样也是safe的。如果你知道你的unsafe操作是绝对没问题的,那么就可以把unsafe封装成safe。
👇
sstudioer: // 这个中文也没问题的, utf8若是多字节首位必是b1xx0_0000 > 'z'; 我只是举个例子;
--
👇
Aya0wind: 你这例子举的不好。 Rust的String是一个utf8字符串,一个字符不是固定1字节的,你要按字节修改本来就会有破坏utf8字符串结构的可能,而C++的string就是一个bytearray,根本没规定编码,是一字节一字节访问的,本来就不一样。 Rust因为要保证不出问题才让你以字节修改字符串为unsafe操作的。你这段C++代码,要是string里面来几个中文字符,这么一操作,整个字符串就要乱了,后面再按utf8规则去使用,搞不好就要出错甚至直接导致程序崩掉,只是无视了问题,而不是解决了问题罢了。
// 这个中文也没问题的, utf8若是多字节首位必是b1xx0_0000 > 'z'; 我只是举个例子;
--
👇
Aya0wind: 你这例子举的不好。 Rust的String是一个utf8字符串,一个字符不是固定1字节的,你要按字节修改本来就会有破坏utf8字符串结构的可能,而C++的string就是一个bytearray,根本没规定编码,是一字节一字节访问的,本来就不一样。 Rust因为要保证不出问题才让你以字节修改字符串为unsafe操作的。你这段C++代码,要是string里面来几个中文字符,这么一操作,整个字符串就要乱了,后面再按utf8规则去使用,搞不好就要出错甚至直接导致程序崩掉,只是无视了问题,而不是解决了问题罢了。
你这例子举的不好。 Rust的String是一个utf8字符串,一个字符不是固定1字节的,你要按字节修改本来就会有破坏utf8字符串结构的可能,而C++的string就是一个bytearray,根本没规定编码,是一字节一字节访问的,本来就不一样。 Rust因为要保证不出问题才让你以字节修改字符串为unsafe操作的。你这段C++代码,要是string里面来几个中文字符,这么一操作,整个字符串就要乱了,后面再按utf8规则去使用,搞不好就要出错甚至直接导致程序崩掉,只是无视了问题,而不是解决了问题罢了。