zoukankan      html  css  js  c++  java
  • Mudo C++网络库第十一章学习笔记

    反思C++面向对象与虚函数

    • C++语言学习可以看《C++ Primer》这本书;
    • 在C++中进行面向对象编程会遇到其他语言中不存在的问题, 其本质原因是C++ class是值语义, 而非对象语义;

    朴实的C++设计

    • 实用当头, 朴实为贵, 好用才是王道;
    • C++ 是一门(最)复杂的编程语言, 语言虽复杂, 不代表一定要用复杂的方式来使用它;
    • 不一定非得有基类和派生类的设计才是好设计;
    • 一个类代表一个概念;
    • 让代码保持清晰, 给我们带来了显而易见的好处;
    • 不要因为某个技术流行而去用它, 除非它确实能降低程序的复杂度;
    • 在C++这样需要自己管理内存和对象生命期的语言里, 大规模使用面向对象、继承、多态多是自讨苦吃;

    C++编译器ABI的主要内容主要包括几个方面:

    • 函数传递的方式, 比如x86-64用寄存器来传函数的前4个整数参数;
    • 虚函数的回调方式, 通常是vptr/vtbl机制, 然后用vtbl[offset]来调用;
    • struct和class的内存布局, 通过偏移量来访问数据成员;
    • name mangling;
    • RTTI 和异常处理的实现;
    • 避免使用虚函数作为库的接口;
      • 因为这样会给保持二进制兼容性带来很大的麻烦;
    • JAVA的库都是.jar文件;

    虚函数作为库的接口的两大用途

    • 调用;
    • 回调, 也就是事件通知, 比如网络库的连接建立, 数据到达, 连接断开等;
    • 混合使用;

    iostream的用途与局限

    • C++ iostream的主要作用是让初学者有一个方便的命令行输入输出试验环境, 在真实的项目中很少用到iostream;
      • 不用花大量的精力在iostream的格式化与manipulator(格式操作符)上;
    • glibc定义的getline函数来读取不定长的行;
      • 返回的是malloc()分配的内存, 要求调用端自己free()掉;
    • iostream不是线程安全的;
    • 用到了多重继承和虚拟继承;
    • Google Protobuf是一种高效的网络传输格式, 它用一种协议描述语言来定义消息格式, 并且自动生成序列花代码;
    • C++的强大之处在于抽象不以性能损失为代价;
    • 数据抽象(data abstraction)是与面向面向对象(object-oriented)并列的一种编程范式(programming pragadigm);

    数据抽象所需的语言设施

    • 支持数据聚合(data aggregation);
    • 全局函数与重载;
    • 成员函数与private数据;
    • 拷贝控制(copy control);
    • C++ class是值语义, copy control是实现深拷贝的必要手段, 而且ADT用到的资源只涉及动态分配的内存, 所以深拷贝是可行的;
    • 操作符重载;
    • 效率无损, 抽象不代表低效;
      • 在C++中, 提高抽象的层次并不会降低效率;
    • 模板与泛型;
    • 数据抽象是C++的重要抽象手段, 适合封装数据, 它的语义简单, 容易使用;
    • 大多数class都是对象语义;

    C++经验谈

    • 练从难处练, 用从易处用;
    • 软件开发一定要时刻注意减少不必要的复杂度;
    • 作为应用程序的开发者, 对技术的运用要明智, 不要为了了解难度系数为10的问题而去强攻难度系数为100的问题, 这就本末倒置了;
    • 用异或来交换变量是错误的;
    • 未定义的行为, 在C/C++语言的一条语句中, 一个变量的值只允许改变一次(像x = x++这种代码都是未定义行为, 因为x有两次写入);
    • 现在的编译器会把std::reverse()这种简单函数自动内联展开, 生成出来的优化汇编代码和其他代码一样快;
    • 不要猜(guess), 要测(benchmark);
    • 不要重载全局::operator new();
      • 按现代C++的手法(RAII)来管理内存, 很难遇到什么内存方面的错误;
    • 内存管理的基本要求:
      • 内存管理的基本要求是不重不漏 -- 既不重复delete, 也不漏掉delete;
      • new/delete配对, 不仅是个数相等, 还隐含了new和delete的调用本身要匹配, 不要东家借的东西西家还;
      • 用系统默认的malloc()分配的内存要交给系统默认的free()去释放;
      • 用系统默认的new表达式创建的对象要交给系统默认的delete表达式去析构并释放;
      • 用系统默认的new[]表达式创建的对象要交给系统默认的delete[]表达式去析构并释放;
      • 用系统默认的::operator new()分配的内存要交给系统默认的::operator delete()去释放;
      • 用placement new创建的对象要用placement delete(为了表述方便, 姑且这么说吧)去析构(其实就是直接调用析构函数);
      • 从某个内存池A分配的内存要还给这个内存池;
      • 如果定制new/delete, 那么要按规矩来;
        • 检查代码中的内存错误;
        • 优化性能;
        • 获得内存使用的统计数据;
    • 脚本语言解释器代码:
      • Python的代码很好读;
    • C语言的static关键字的两种用法:
      • 用于函数内部修饰变量, 即函数内的静态变量; 使用静态变量的函数一般是不可重入的, 也不是线程安全的;
      • 用在文件级别(函数体之外), 修饰变量或函数, 表示该变量或函数只能在本文件可见, 其他文件看不到, 也访问不到该变量或函数(interal linkage);
    • C++语言的static关键子的四种用法:
      • static关键字又有了两种新用法: 用于修饰class的数据成员, 即所谓的静态成员, 这种数据成员的生存期大于class的对象(实体/instance);
      • 静态成员是每个class有一份, 普通数据成员是每个instance(实例)有一份, class variable(类变量)和instance variable(实例变量);
      • 用于修饰class的成员函数, 即所谓的静态成员函数, 静态成员函数只能访问class variable和其他静态程序函数, 不能访问instance variable或instance method;
    • 协议设计是网络编程的核心:
      • 消息格式: XML, JSON, Protobuf, 难的是消息内容;
    • 网络编程的三个层次:
      • 读过教程和文档, 做过练习 -- 读过《UNIX网络编程》《TCP/IP详解》并理解TCP/IP协议, 读过本系统的manpage;
      • 熟悉本系统TCP/IP协议栈的脾气;
        • 有可能出现TCP自连接(self-connection), 程序应该有所准备;
        • Linux内核会有bug, 比如某种TCP拥塞控制算法曾经出现TCP window clamping(窗口错位)bug, 导致吞吐量暴跌, 可以选用其他拥塞控制算法来绕开(work around)这个问题;
      • 自己写过一个简单的TCP/IP stack;
    • TCP网络编程有三个例子最值得学习研究: 分别是echo, chat, proxy都是长连接协议;
      • proxy的作用: 连接的管理更加复杂, 既要被动接受连接, 也要主动发起连接, 既要主动关闭连接, 也要被动关闭连接, 还要考虑两边速度不匹配;
    • 三本必看的书:
      • 谈到Unix编程和编程编程, W.Richard Stevens是个绕不开的人物;
        • [APUE]、两卷《UNIX网络编程》、三卷《TCP/IP详解》;
        • [UNPv2]其实跟网络编程关系不大, 是[APUE]在多线程和进程间通信(IPC)方面的补充;
        • 《TCP/IP详解》三卷, 用处不同, 应该区别对待;
      • 第一本《TCP/IP Illustrated, Vol. 1: The Protocols》(TCP/IP详解);
        • 从使用者(程序员)的角度, 以tcpdump为工具, 对TCP协议抽丝剥茧, 娓娓道来;
        • TCP作为一个可靠的传输层协议, 其核心有三点:
          • Positive acknowledgement with retransmission(对重传的积极响应) -- 可靠性;
          • Flow control using sliding window(包括Nagle算法等) -- 提高吞吐量;
          • Congestion(拥塞) control(包括slow start、congestion avoidance、fast retransmit) -- 防止过载造成丢包;
        • TCP像是一个自适应的节流阀, 根据管道的拥堵情况自动调整阀门的流量;
      • 第二本《Unix Network Programming, Vol.1:Networking API》统称UNP;
        • UNP是Sockets API的权威指南;
        • 网络编程远不是使用那十几个Sockets API那么简单, 一定要熟悉TCP/IP协议及其外在表现(比如打开和关闭Nagle算法对收发包延时的影响);
        • UNP中问版《UNIX网络编程》翻译得相当好, 译者杨继张先生是真懂网络编程的;
        • UNP很详细, 面面俱到, UDP、TCP、IPv4、IPv6都讲到了;
        • 讲得太详细, 重点不够突出;
          • 在具备基础之后, 学习任何新东西, 都要抓住主线, 突出重点, 对于关键理论的学习, 要集中精力, 速战速决;
          • 作者是先看的TCPv1, 花了大约两个月的时间, 然后再读UNP和APUE;
        • 第三本《Effective TCP/IP Programming》;
          • 这本书属于专家经验总结类的书籍;
        • 还值得一看的书:
          • 《TCP/IP Illustrated, Vol.2: The Implementation》, 称为TCPv2;
          • 工作中大可以把IP视为host-to-host的协议;
          • 《Pattern-Oriented Software Architecture Volume 2: Patterns for Concurrent and Networked Objects》, 简称POSA2;
            • 这本书总结了开发并发网络服务程序的模式, 是对UNP很好的补充;
            • POSA2强调模块化, 网络通信交给library/framework去做, 程序员写代码只关注业务逻辑(这是非常重要的思想);
            • 这本书对深入理解常用的event-driven网络库(libevent, Java Netty, Java Mina, Perl POE, Python Twisted)也很有帮助;
            • POSA2的代码是示意性的, 思想很好, 细节不佳;C++代码没有充分考虑资源的自动化管理(RAII);
    • 很多企业内部使用C++来构建自己的分布式系统基础架构, 并且有替换Java开源实现的趋势;
    • 学习C++只需要读一本大部头《The C++ Programming Language》或《C++ Primer》;
      • 《C++ Primer》的主要内容是精解C++语法(syntax)与语意(semantics)并介绍C++标准库的大部分内容(含STL);
    • C++的开源库: Google的Protobuf, leveldb, PCRE的C++封装, 还有就是作者的muduo库;
    • 如有时间可以读读Chromium中基础库源码, 在读Google开源的C++代码时要连注释一起细读;
    • 不建议一开始就读STL或Boost的源码, 因为编写通用的C++模板库和编写C++应用程序的知识体系相差很大;
    • 《Effective C++中文版》,《泛型编程与STL》, 《C++编程规范》;
    • 避免写出依赖于函数实参求值顺序的代码, C++操作读的优先级、结合性与表达式的求值顺序是无关的;
    • Google的C++编程规范和LLVM编程规范;
  • 相关阅读:
    POJ 3261 Milk Patterns (求可重叠的k次最长重复子串)
    UVaLive 5031 Graph and Queries (Treap)
    Uva 11996 Jewel Magic (Splay)
    HYSBZ
    POJ 3580 SuperMemo (Splay 区间更新、翻转、循环右移,插入,删除,查询)
    HDU 1890 Robotic Sort (Splay 区间翻转)
    【转】ACM中java的使用
    HDU 4267 A Simple Problem with Integers (树状数组)
    POJ 1195 Mobile phones (二维树状数组)
    HDU 4417 Super Mario (树状数组/线段树)
  • 原文地址:https://www.cnblogs.com/longjiang-uestc/p/9849444.html
Copyright © 2011-2022 走看看