《C++ Primer》读书笔记(8.1,8.2,8.4)

来源:互联网 发布:怎么推广自己的淘宝店 编辑:程序博客网 时间:2024/05/21 11:20

关于局部域

如果在全局域中声明了变量low,那在嵌套局部域中使用的low 仍然指向局部的low 的声明 全局声明会被局部声明隐藏起来


关于全局域

程序中用到的全局对象也必须有一个定义。全局对象和非inline全局函数在一个程序内只能被定义一次,而只要给出的定义完全相同即可。inline 函数可以在一个程序中被定义多次 这要求全局对象和函数或者只有一个定义,或者在一个程序中有多个完全相同的定义。这样的要求被称为一次定义法则  ODR [one definition rule]


空悬指针[dangling pointer]

当一个自动变量的地址被存储在一个生命期长于它的指针时,该指针被称为空悬指针[dangling pointer]

        #include "Matrix.h"         Matrix* trouble( Matrix *pm )         {               Matrix res;               // 用 pm做一些事情               // 把结果赋值给 res               return &res; // 糟糕 !         }         int main()         {               Matrix m1;               // ...               Matrix *mainResult = trouble( &m1 );               // ...         } 


寄存器自动对象

函数中频繁被使用的自动变量可以用register 声明,如果可能的话,编译器会把该对象装载到机器的寄存器中。如果不能够的话 则对象仍位于内存中,出现在循环语句中的数组索引和指针是寄存器对象的很好例子

如果所选择的变量被频繁使用,则寄存器变量可以提高函数的执行速度。关键字register对编译器来说只是一个建议有些编译器可能忽略该建议。而是使用寄存器分配算法找出最合适的候选放到机器可用的寄存器中,因为编译器知道运行该程序的机器的结构,所以它选择寄存器的内容时常常会做出更有意义的决定 。


静态局部变量
static 静态局部对象具有静态存储持续期间[static storage duration]静态范围[static extent]。虽然它的值在函数调用之间保持有效,但是其名字的可视性仍限制在其局部域内,静态局部对象在程序执行到该对象的声明处时被首次初始化 

         #include <iostream>          int traceGcd( int v1, int v2 )          {                static int depth = 1;                cout << "depth #" << depth++ << endl;                if ( v2 == 0 ) {                   depth = 1;                   return v1;                }                return traceGcd( v2, v1%v2 );          } 
    与静态局部对象depth 相关联的值在traceGcd()的调用之间保持有效 初始化只在traceGcd()首次被调用时执行一次 下面的小程序使用了traceGcd() 
         #include <iostream>          extern int traceGcd(int, int);          int main() {                int rslt = traceGcd( 15, 123 );                cout << "gcd of (15,123): " << rslt << endl;                return 0;          } 
    编译并运行该程序 产生下列输出 

         depth #1 
         depth #2 
         depth #3 
         depth #4 
         gcd of (15,123): 3 


 关于auto_ptr

    auto_ptr 是C++标准库提供的类模板,它可以帮助程序员自动管理用new 表达式动态分配的单个对象(不幸的是 对用new 表达式分配的数组管理没有类似的支持 我们不能用auto_ptr 存储数组 如果这样做了 结果将是未定义的

        auto_ptr< int > pi( new int( 1024 ) );        if ( *pi != 1024 )               // 喔, 出错了         else *pi *= 2;

    auto_ptr 类模板背后的主要动机是支持与普通指针类型相同的语法,但是为auto_ptr 对象所指对象的释放提供自动管理。根据一般的常识,你可能会认为这种额外的安全性一定来自于执行效率的开销,但实际情况并不是这样。因为对这些操作的支持都是内联的,它们由编译器在调用点上展开,所以使用auto_ptr 对象并不比直接使用指针代价更高。 

不能够在auto_ptr 对象被定义之后 再用new 表达式创建对象的地址来直接向其赋值,而是应该使用reset 

              pi.reset( new int( 1024 ) ); 

   release()操作允许将一个auto_ptr 对象的底层对象初始化或赋位给第二个对象 而不会使两个auto_ptr 对象同时拥有同一对象的所有权 release()不仅像get()操作一样返回底层对象的地址 而且还释放这对象的所有权 前面代码段可被正确改写如下 
        // ok: 两个对象仍然指向同一个对象         // 但是, pstr_auto 不再拥有拥有权         auto_ptr< string >               pstr_auto2( pstr_auto.release() ); 




原创粉丝点击