<>读后感-001

语言特性 Go语言作为一门全新的静态类型开发语言,与当前的开发语言相比具备众多令人兴奋不已 的新特性。
Go语言最主要的特性:

    1. 自动垃圾回收
    1. 更丰富的内置类型
    1. 函数多返回值
    1. 错误处理
    1. 匿名函数和闭包
    1. 类型和接口
    1. 并发编程
    1. 反射
    1. 语言交互性

比较有意思的是作者对自动垃圾回收精确的描述,但有些描述不一定完全准确:

自动垃圾回收可以先看下不支持垃圾回收的语言的资源管理方式,以下为一小段C语言代码:

void foo() {
 char* p = new char[128]; ... // 对p指向的内存块进行赋值 
func1(p); // 使用内存指针 
delete[] p; } 
  • 各种非预期的原因,比如由于开发者的疏忽导致最后的delete语句没有被调用,都会引发 经典而恼人的内存泄露问题。假如该函数被调用得非常频繁,那么观察该进程执行时,会发现该进程所占用的内存会一直疯长,直至占用所有系统内存并导致程序崩溃,而如果泄露的是系 统资源的话,那么后果还会更加严重,最终很有可能导致系统崩溃。
  • 手动管理内存的另外一个问题就是由于指针的到处传递而无法确定何时可以释放该指针所指向的内存块。假如代码中某个位置释放了内存,而另一些地方还在使用指向这块内存的指针, 那么这些指针就变成了所谓的“野指针”(wild pointer)或者“悬空指针”(dangling pointer),对 这些指针进行的任何读写操作都会导致不可预料的后果。
  • 由于其杰出的效率,C和C++语言在非常长的时间内都作为服务端系统的主要开发语言,比 如Apache、Nginx和MySQL等著名的服务器端软件就是用C和C++开发的。然而,内存和资源管 理一直是一个让人非常抓狂的难题。服务器的崩溃十有八九就是因为不正确的内存和资源管理导致,更讨厌的是这种内存和资源管理问题即使被发现了,也很难定位到具体的错误地点,导致无数程序员通宵达旦地调试程序。 这个问题在多年里被不同人用不同的方式来试图解决,并诞生了一些非常著名的内存检查工具,比如Rational Purify、Compuware BoundsChecker和英特尔的Parallel Inspector等。从设计方法的 角度也衍生了类似于内存引用计数之类的方法(通常被称为“智能指针”),后续在Windows平台 上标准化的COM出现的一个重要原因就是为了解决内存管理的难题。但是事实证明,这些工具和方法虽然能够在一定程度上辅助开发者,但并没法让开发者避免通宵调试这样又苦又累的工作。
  • 到目前为止,内存泄露的最佳解决方案是在语言级别引入自动垃圾回收算法(Garbage Collection,简称GC)。所谓垃圾回收,即所有的内存分配动作都会被在运行时记录,同时任何对 该内存的使用也都会被记录,然后垃圾回收器会对所有已经分配的内存进行跟踪监测,一旦发现 有些内存已经不再被任何人使用,就阶段性地回收这些没人用的内存。当然,因为需要尽量最小 化垃圾回收的性能损耗,以及降低对正常程序执行过程的影响,现实中的垃圾回收算法要比这个 复杂得多,比如为对象增加年龄属性等,但基本原理都是如此。
    自动垃圾回收在C/C++社区一直作为一柄双刃剑看待,虽然到C++0x(后命名为C++11)正 式发布时,这个呼声颇高的特性总算是被加入了,但按C++之父的说法,由于C++本身过于强大, 导致在C++中支持垃圾收集变成了一个困难的工作。假如C++支持垃圾收集,以下的代码片段在 运行时就会是一个严峻的考验:
int* p = new int; 
p += 10; // 对指针进行了偏移,因此那块内存不再被引用 
// …… 这里可能会发生针对这块int内存的垃圾收集 …… 
p -= 10; // 咦,居然又偏移到原来的位置 
*p = 10; // 如果有垃圾收集,这里就无法保证可以正常运行了

微软的C++/CLI算是用一种偏门的方式让C++程序员们有机会品尝一下垃圾回收功能的鲜美味道。

  • 在C/C++之后出现的新语言,比如Java和C#等,基本上都已经自带自动垃圾回收功能。 Go语言作为一门新生的开发语言,当然不能忽略内存管理这个问题。又因为Go语言没有C++ 这么“强大”的指针计算功能,因此可以很自然地包含垃圾回收功能。因为垃圾回收功能的支持, 开发者无需担心所指向的对象失效的问题,因此Go语言中不需要delete关键字,也不需要free() 方法来明确释放内存。例如,对于以上的这个C语言例子,如果使用Go语言实现,我们就完全不 用考虑何时需要释放之前分配的内存的问题,系统会自动帮我们判断,并在合适的时候(比如CPU 相对空闲的时候)进行自动垃圾收集工作。

自我验证体会,有些观点不一定完全准确,比如C/C++高效的指针运算是别的语言所不具备的,但相应的自动垃圾回收变的几乎不可实现,但相应的提供了智能指针的解决方案。
智能指针在C++11版本之后提供,包含在头文件中,shared_ptr、unique_ptr、weak_ptr。

  • 1.shared_ptr多个指针指向相同的对象。shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。每使用他一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0时,自动删除所指向的堆内存。shared_ptr内部的引用计数是线程安全的,但是对象的读取需要加锁。
  • 2. unique_ptr“唯一”拥有其所指对象,同一时刻只能有一个unique_ptr指向给定对象(通过禁止拷贝语义、只有移动语义来实现)。相比与原始指针unique_ptr用于其RAII的特性,使得在出现异常的情况下,动态资源能得到释放。unique_ptr指针本身的生命周期:从unique_ptr指针创建时开始,直到离开作用域。离开作用域时,若其指向对象,则将其所指对象销毁(默认使用delete操作符,用户可指定其他操作)。unique_ptr指针与其所指对象的关系:在智能指针生命周期内,可以改变智能指针所指对象,如创建智能指针时通过构造函数指定、通过reset方法重新指定、通过release方法释放所有权、通过移动语义转移所有权。
  • 3. weak_ptr是为了配合shared_ptr而引入的一种智能指针,因为它不具有普通指针的行为,没有重载operator*和->,它的最大作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况。weak_ptr可以从一个shared_ptr或者另一个weak_ptr对象构造,获得资源的观测权。但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加。使用weak_ptr的成员函数use_count()可以观测资源的引用计数,另一个成员函数expired()的功能等价于use_count()==0,但更快,表示被观测的资源(也就是shared_ptr的管理的资源)已经不复存在。weak_ptr可以使用一个非常重要的成员函数lock()从被观测的shared_ptr获得一个可用的shared_ptr对象, 从而操作资源。但当expired()==true的时候,lock()函数将返回一个存储空指针的shared_ptr。

你可能感兴趣的:(<>读后感-001)