随笔(2014.9)

来源:互联网 发布:淘宝旺旺名字怎么复制 编辑:程序博客网 时间:2024/04/29 13:06

1. 智能指针问题都可以在代码中使用引用记数的方式替代掉,如果待删除的对象同时最多只被一个对象回调,那么可以用一个flag来表示“计数”,对象请求发送后与回调后改变这个标志位。

 

2. time_t表示1970年0点到现在的秒数。

 

3. 对于异步消息的问题,可能出现一种恶性循环情况,当服务器处理不了很多请求的时候,如果客户端定时发送异步请求那么服务器的未处理请求就会越来越多,而客户端获取到的请求结果也是越来越慢。如果用异步的方式循环发送消息,那么最后在消息回复后(或者超时后)通知发送者上次消息已经处理结束,发送者在发送下一个异步请求,否则不在发送请求。

 

4. 对于设备的管理,如果设备之间有父子设备的关系,那么代码中设备的组织方式有两种,一种是组合模式类似,子设备存在于父设备之中,这样的好处是数据的一致性有天然的保证,父设备删除的时候子设备肯定会删除,没有父设备子设备肯定也插入不进入,而且获取父设备子设备比较方便,但是这样的话设备对象较大,不方便拷贝(可能有子设备指针)。而且顶层父设备的接口比较多,对象拷贝比较麻烦。第二种就是按照类别来存储,一类设备放在一个list或者map中,然后通过代码来保证数据的一致性,设备对象方便拷贝,遍历同类设备比较方便,如果设备有唯一id,那么查找会很方便。如果设备数量不多,还是有先推荐第一种方式,父设备接口大,不是问题,如果父设备的接口小了,那么接口会转移到Manager中,拷贝不方便也不是问题,如果使用智能指针的话,而且一般不会拷贝顶层父设备,只拷贝必要的信息就可以了像ip与id等等,不必要拷贝全部对象。

 

5. 接着上面的问题,函数的参数最好也满足“最少知道”的原则,如果只需要一个id,没有必要把全部的设备对象指针传递过来,这样不仅函数功能明确,也减少了指针使用造成的错误与锁开销。

 

6. “对象构造要做到线程安全,惟一的要求是在构造期间不要泄露 this 指针,即:不要在构造函数中注册任何回调,也不要在构造函数中把 this 传给跨线程的对象,即便在构造函数的最后一行也不行”,这里里面有个特例,如果类是个基类,那么可以在最后一行把this指针给别人。不会有“半成品”被使用的情况

 

7. 在64位的程序中,传递8个字节的结构体如果使用by value甚至比by reference速度更快

 

8. “跨平台和高性能是矛盾的。跨平台意味着要抽象出多个平台的共性,以最 general 的方式编写上层代码。而高性能则要求充分发挥平台的特性,剑走偏锋,用尽平台能提供的一切加速手段,哪怕与其他平台不兼容。网络编程对此尤为敏感。”

 

9. http://blog.csdn.net/chgaowei/article/details/6427731
1、对象的静态类型:对象在声明时采用的类型。是在编译期确定的。
2、对象的动态类型:目前所指对象的类型。是在运行期决定的。对象的动态类型可以更改,但是静态类型无法更改。

指针和引用的动态类型和静态类型可能会不一致,但是对象的动态类型和静态类型是一致的。

静态绑定发生于数据结构和数据结构间,程序执行之前。静态绑定发生于编译期,因此不能利用任何运行期的信息。它针对函数调用与函数的主体,或变量与内存中的区块。动态绑定则针对运行期产生的访问请求,只用到运行期的可用信息。在面向对象的代码中,动态绑定意味着决定哪个方法被调用或哪个属性被访问,将基于这个类本身而不基于访问范围。

动态绑定难道是静态语言所留的后门,之所以在编译期间不绑定,在运行时后绑定,难道是编译器不知道如何绑定、

 

10. http://blog.csdn.net/solstice/article/details/5364096 对ace的历史与简述的一篇文章,简单总结起来有以下观点,ace可以参看的书与文献不多,自己使用的过程中也有这个问题,好像就马维达翻译过三本书与ace相关的,还有两本红色的,竟然网上都没的卖。对于30w行代码的一个中间件可以参考的东西可以说是严重不匹配。第二个观点就是使用过程中非常容易出错,这可能也是第一个原因有关系,但是最主要的原因是复杂。第三个观点是代码质量不高,这点自己无法评论,因为自己代码质量也不怎么靠谱。第四个观点是过于复杂,从代码量上看30多w行代码,甚至比很多操作系统代码还多。但是虽然有上述缺点,ace的优点也就目的就是一个,移植性好,但这一优点必然会对性能稍有影响。文章最后作者观点“网络库要解决现实的问题,满足现实的需要,而不是把 features/patterns 堆在那里等别人来用。应该先有应用,再提炼出库。而不是先造库,然后寻求应用。”。根据应用提炼库自然会高效简洁,但是肯定会会费一定时间。我觉得是否需要定制库肯定要根据使用的规模,应用场景来决定,一个项目组就十个人肯定来不及维护网络库,在大规模的应用,对性能有要求的时候与关系型云数据库一样,都需要定制化。

 

11. 当析构函数遇到多线程──C++ 中线程安全的对象回调http://blog.csdn.net/solstice/article/details/5238671 ,介绍了c++多线程回调对象的容易出现的几个错误,第一个容易犯的错误是在构造函数中把this指针泄露出去,这样可能造成通过this指针访问半成品对象,尤其是有继承关系的时候。第二个容易犯的错误是在析构函数中加锁,在析构函数中会把锁对象也析构掉,这样对于锁的判断就会导致未定义情况。第三个容易犯的错误是使用share_ptr时候出现的循环引用,会导致对象无法释放,内存泄露。可以使用weak_ptr方式来解决这个问题。还有一个点需要引起一定注意,使用share_ptr可能会延长对象的生命周期,例如在使用bost::bind()的时候。
 
12. “我个人倾向于使用不可重入的 Mutex ,例如 pthreads 默认提供的那个,因为 “ 要求
Mutex 可重入 ” 本身往往意味着设计上出了问题。 Java 的 intrinsic lock 是可重入的, 因
为要允许 synchronized 方法相互调用,我觉得这也是无奈之举。”有意思的观点,使用可重入mutex为设计的问题,可重入的mutex陷阱多么?效率差么?

 

13. 如何写可测的代码?http://blog.csdn.net/toy_shop_owner/article/details/25448849 主要注意就是设计上的不要依赖太强,尽可能可功能单一的函数,而且能够控制函数的输入输出,如果输出与内部的静态函数有关系,那么可以把静态的东西抽象封装,然后再注入到函数或其他对象中。

 

14.“为什么 non-virtual 函数比 virtual 函数更健壮?因为 virtual function 是 bind-by-vtable-offset,而 non-virtual function 是 bind-by-name。加载器 (loader) 会在程序启动时做决议(resolution),通过 mangled name 把可执行文件和动态库链接到一起。就像使用 Internet 域名比使用 IP 地址更能适应变化一样。”,大型的程序库最好不要使用c++的虚函数作为接口。

 

15. telnet ip port 格式不是ip:port 而是ip空格port

 

16. 类型安全的定义“In computer science, type safety is the extent to which a programming language discourages or prevents type errors. A type error is erroneous or undesirable program behaviour caused by a discrepancy between differing data types for the program's constants, variables, and methods (functions), e.g., treating an integer (int) as a floating-point number (float). Type safety is sometimes alternatively considered to be a property of a computer program rather than the language in which that program is written; that is, some languages have type-safe facilities that can be circumvented by programmers who adopt practices that exhibit poor type safety. ”

 

17. 对于基础设施导出的接口方法,可以参考一些人们常用的库,如stl,mfc等等,最好不要自创。

 

18.垃圾收集机制(Garbage Collection)批判http://blog.csdn.net/myan/article/details/1906 ,“Java的GC实际上是JVM中的一个独立线程,采用不同的算法策略来收集heap中那些不再有
reference指向的垃圾对象所占用的内存。但是,通常情况下,GC线程的优先级比较低,只有在当前程序空闲的时候才会被调度,收集垃圾。当然,如果JVM感到内存紧张了,JVM会主动调用GC来收集垃圾,获取更多的内存。请注意,Java的GC工作的时机是:1. 当前程序不忙,有空闲时间。2.空闲内存不足。现在我们考虑一种常见的情况,程序在紧张运行之中,没哟空闲时间给GC来运行,同时机器内存很大,JVM也没有感到内存不足,结果是什么?对了,GC形同虚设,得不到调用。于是,内存被不断吞噬,而那些早已经用不着的垃圾对象仍在在宝贵的内存里睡大觉”,“而且GC工作的方式也很不好评价,一种方法是一旦有机会回收内存,就把所有的垃圾都回收。你可以想象,这要花很长时间(几百M的垃圾啊!),如果你这时侯正在压下开炮的按钮,GC却叫了暂定,好了,你等死吧!另一种方法,得到机会之后,回收一些内存,让JVM感到内存不那么紧张时就收手。结果呢,内存里始终有大批垃圾,程序始终在半死不活的荡着。最后,GC可以每隔一段时间就运行一次,每次只回收一部分垃圾,这是现在大部分JVM的方式,结果是内存也浪费了,还动不动暂停几百毫秒”
“据统计,目前的Java程序运行期间占用的内存通常为对应C++程序的4-20倍。”

 

19. breaking up a lock is not the only way to reduce contention, and contention can be (and often is) more easily reduced by decreasing the hold time of the lock.

 

20. 强引用和弱引用

一个强引用当被引用的对象活着的话,这个引用也存在(就是说,当至少有一个强引用,那么这个对象就不能被释放)。boost::share_ptr就是强引用。

相对而言,弱引用当引用的对象活着的时候不一定存在。仅仅是当它存在的时候的一个引用。弱引用并不修改该对象的引用计数,这意味这弱引用它并不对对象的内存进行管理,在功能上类似于普通指针,然而一个比较大的区别是,弱引用能检测到所管理的对象是否已经被释放,从而避免访问非法内存。

boost::weak_ptr

boost::weak_ptr<T>是boost提供的一个弱引用的智能指针,它的声明可以简化如下:

 

namespace boost {    template<typename T> class weak_ptr {    public:        template <typename Y>        weak_ptr(const shared_ptr<Y>& r);        weak_ptr(const weak_ptr& r);        ~weak_ptr();        T* get() const;         bool expired() const;         shared_ptr<T> lock() const;    }; }


可以看到,boost::weak_ptr必须从一个boost::share_ptr或另一个boost::weak_ptr转换而来,这也说明,进行该对象的内存管理的是那个强引用的boost::share_ptr。boost::weak_ptr只是提供了对管理对象的一个访问手段。

boost::weak_ptr除了对所管理对象的基本访问功能(通过get()函数)外,还有两个常用的功能函数:expired()用于检测所管理的对象是否已经释放;lock()用于获取所管理的对象的强引用指针。

0 0
原创粉丝点击