美文网首页
2020-07-09

2020-07-09

作者: Quarkstar9 | 来源:发表于2020-07-10 00:53 被阅读0次

    颓废!今天效率不太行。主要是学的累了,就当放松一下。
    今天上午就看了个trie树。晚上继续推进csapp。下午似乎啥都没做。睡觉,休息为主。嗷,今天还看了很多和cpp语法相关的知识。如const的用法和模板元编程。
    今天就吃了点儿炒面片。不太想吃饭。但是蜂蜜🍯柠檬🍋茶还是喝了两大杯。好喝!
    话不多说,冲冲冲!

    Trie

    trie,字典树,很简单。树的每一条从根结点到叶子结点的路径代表了一个单词。用来单词的快速查找/前缀匹配。这个代码就不用写了吧,太简单了。等以后看到ac自动机一块儿说吧。

    const template-> cpp

    const看了一堆还是乱糟糟的,一言以蔽之,const修饰的对象不可变。其他的等我彻底弄明白出个总结吧。这里只放一些例子。

    const int a = 1;
    const int * p;
    int const * p;
    void fn(const & T);
    void fn(const T &);
    void fn() const;
    void fn(const T&&);
    

    cpp设计的也太乱了……,感觉字母已经不太够用了。
    最后一个是右值引用。右值从源头上来说是等式右面的值(当然现实并非如此),一般来说能取地址的址是左值,其余是右值。但是这个也不准确,也有反例:P。
    右值,移动语义与完美转发,基本替代了new与delete,其他语言都是引用语义,cpp在值语义的路上一路狂奔。我个人觉得引用语义虽然简单,但是性能是永远绕不过去的坎。
    cpp是怎么做的呢?首先有RAII,变量声明后建构,离开作用域时析构,完成了资源的自动管理。之后有移动语义。以前对象作为参数或者返回值都是拷贝构造:我在需要用的地方先复制一份,然后把原来的对象删除。现在有了简单明了的移动语义,事情就简单了很多,就是一个单纯的指针移动。通过移动语义,相当于更改了原来资源的生命周期,从一个作用域延长到另一个作用域,并在这个作用域结束时析构。我觉得这个设计真的很棒了,比如函数给我返回一个vector,new与delete的时代,我接收到一个函数指针,我需要记得用完后delete vector,进而出现了内存泄漏、多次释放、野指针等问题。通过移动语义,vector就像是我函数栈上的空间一样,不需要我手动删除,退出此函数时自动释放,也就没有各种问题。最近无GC的手动内存管理——rust比较流行,以后有时间学习一下。
    今天还有一个好玩的,就是类型表示法。c语言其实也不是前缀也不是后缀,是中缀,所以乱死了。前缀是想java一样的,很整洁。int (*p[10])(char *),怎么看怎么奇怪。

    int fn(int a); // java...
    fn(a : int) -> int; // rust / kotlin / typescript...
    fn:: Int -> Int // haskell
    

    我觉得这方面都没法和haskell比,人家专门玩类型系统的。但haskell这个写法在其他语言未必合适。
    template模板元编程。我觉得有趣的一点是编译期计算。比如一个程序,输入x,y,求fib(x) / fib(y)。如果每次运行程序都把fib算一遍太费事了,最简单的方法就是把fib打表写到程序里,算个除法直接输出。但这样就有了一个问题:我不能开个数组比如const int[] = {0, 1, 1, 2...};万一输错一位,全完了。所以还是得写程序。但我不希望它每次运行都算一遍,那我就放到编译期计算。刚好cpp里有模板。我个人觉得模板其实就是fp里的替换模型,但是在cpp里配合模板这个难受的语法,一不小心几万行的报错,还不能debug,变得很不好写。但是模板又太有用了,编译期计算将程序性能进一步提高,而且有很多想不到的用处,(~﹃~)~zZ。
    来个例子来个例子。这个不用解释,一看就懂。

    template<unsigned n>
    struct Factorial {
      enum {value = n * Factorial<n-1>::value;}
    };
    template<>
    struct Factorial<0> {
      emun {value = 1 };
    };
    

    再感叹一下cpp太强了,无论多奇怪,都能加进来。还是那句话,cpp是一个语言联邦。
    但我有个奇思妙想嗷。这事儿在scheme里能不能搞。那有人就会问了,scheme一个解释性语言,都没有编译,哪来的编译期计算。来一小段代码。就用js。

    function test() {
      fib = computeFib();
      return function(x, y) { return fib[x] / fib[y];};
    }
    

    这不就是个闭包吗?但你细品一下,是不是初始计算只发生了一次?我们发布程序时能不能不止发布代码,而是把环境也一起发布呢?数据已经在环境中,就不需要再次计算了。我觉得这个更棒。不过那还得指定一个通用环境格式。想想也不easy。先留个坑,以后研究研究再回来。

    位表示

    本来打算写的,csapp晚上看的。但是太晚了,不写了。明天带着整数,浮点表示一起写吧。
    然后过两天把以前的坑填填。感觉留的坑太多了🕳。

    睡了。
    瘦尽灯花又一宵。

    相关文章

      网友评论

          本文标题:2020-07-09

          本文链接:https://www.haomeiwen.com/subject/etpycktx.html