C++笔记(一、二)

C++学习笔记

        很早就决定做基于C++的windows编程了,并且也已经在这条路上走了一段时间了,虽说不长,但绝对时间还算及格吧,最近几天效率莫名的开始下滑,自习室能坐下来,但遇到问题总是会首先想到先把它标记一下,等以后解决。这也不是办法,疲于无法回避这个问题,突然想到之前研读红楼梦的经历,当时在阅读时,会在自己感觉重要或者有心得的地方做点笔记,通读之后回过头来复阅时感觉效果破佳,所以准备用在这里,其实还有一个原因,这个保密。这次不准备在书上眉批,原因有三,空间过于狭小,并且交流起来颇有不便,故键盘录入,也算是指法练习了。以后回过头来再看自己这些青涩的记录,或许会再一次莞尔一笑吧。关于C++的书,我的桌面也摆了不少,并且也都算得上经典书从,从哪开始说起呢,这是个问题,其实也算不上,因为有C++ primer的存在,这个问题就不是问题了,这本书在C++领域的地位不用过多解释,这本书通读过两遍(断断续续的多少遍就说不清了),每次读都有新的体会,基于以上原因,故首先批它。

                                          第一章

     <iostream>和<iostream.h>格式不一样,前者没有后缀,现在基本也都是在用它(钱能的C++书还是带.h的版本,所以他的程序在非古董级的编译器上都不能运行通过,在编译器include文件夹里面可以看到,二者是两个文件,打开文件可以发现,里面的代码是不一样的。.h的头文件新版c++标准已经明确提出不支持了,早的实现将标准库功能定义在全局空间里,声明在带.h后缀的头文件里,c++标准为了和C区别开,也为了正确使用命名空间,规定头文件不使用后缀.h。 因此,当使用<iostream.h>时,相当于在c中调用库函数,使用的是全局命名空间,也就是早期的c++实现;当使用<iostream>的时候,该头文件没有定义全局命名空间,必须使用namespace std;这样才能正确使用cout。

    cin,cout定义程序库里面的命名空间std里面,使用前要让其名字曝光,否则编译不会通过。之所以可以级联使用,是因为它们返回的是它们本身的引用。之所以能输出多种类型是因为它被重载了。

    endl是一个操纵符,它不但实现了换行操作,而且还对输出缓冲区进行刷新。什么意思?解释一下在执行输出操作之后,数据并非立刻传到输出设备,而是先进入一个缓冲区,当适宜的时机(如设备空闲)后再由缓冲区传入,也可以通过操纵符flush,ends,或unitbuf进行强制刷新。

    当成对注释符号跨越多行时,最好能直观地指明每一行都是注释,C++ primer推荐的风格是在注释的每一行以星号开始。最好是将注释块放在所解释代码的上方。成对的注释符号不能嵌套

    当我们试图把一个超出变量取值范围的值赋给一个变量时,其结果取决于这种类型是unsigned还是signed类型。对于unsigned,编译器将该值与unsigned类型可以取值的个数求模,然后取得所得值。对于signed类型,很多的编译器与unsigned类型的处理方式一致,但不能保证所有编译器都是如此。

    在对程序进行计数时,使用unsigned类型比较明智。这可以避免值越界,导致结果为负数的可能。有些机器上使用double类型比使用float类型计算要快的多,在实际的编译器中,在VC下我测试过,精度不高的浮点数都分配8个字节存储,亦即都默认当作double类型。long double 类型提供的精度通常没有必要,而且还需要承担额外的运行代价。

    处理长字符串有一个很基本的方法:在一行的末尾加一反斜线符号,可将此行和下一行当做同一行处理这继承C,不过此时反斜线(backslash)必须是每一行的最后一个字符,其后不能有字符。

第二章

    C++支持两种初始化变量的形式:(1)复制初始化,如int a=11(2)直接初始化 如int a(11);要明白一点:初始化不等于赋值。这可以拿自定义类型类的初始化来帮助理解。一是在构造函数内初始化,二是调用复制构造函数用其他对象初始化。而赋值(这是个重要概念)是指擦除对象的当前值并用新值代替。如:

user_defined_class a(199); 

user_defined_class b(a);

user_defined_class b=a;

    b(a)与b=a的区别就是初始化与赋值的区别。对内置类型来说复制初始化和和直接初始化差别很小。

    对于内置类型,系统有时候会帮我们初始化变量。但只有全局的、静态的或是在名字空间内的变量才会被编译器自动初始化。局部变量不被自动初始化。对于类类型依赖于构造函数。对于没有提供构造函数的类,编译器会自动产生一个默认的构造函数但是它不初始化类内内置类型的各成员变量(不过默认构造函数为他们在栈或堆区分配内存,里面是垃圾值,在全局区是全0值)。

    typedef可以用来定义类型的同义词。typedef通常被用于以下三种目的:1.为了隐藏特定类型的实现,强调使用该类型的目的;2.简化复杂的类型定义,使其更易理解;3.允许一种类型用于多个目的,同时使得每次使用该类型的目的明确。

    C++程序通常有许多文件组成,为了让多了文件访问相同的变量,C++区分了声明和定义声明用于向程序表明变量的类型和名字,可以通过使用extern关键字声明变量而不定义它。它说明变量定义在程序的其它地方。变量可以声明多次,但只能定义一次如果声明有初始化式,此时它被当做定义。如extern int i=10;另外注意只有当extern声明位于函数外部时才可以含有初始化式。任何在多个文件中使用的变量都需要有与定义分离的声明。在这种情况下,一个文件含有变量的定义 ,使用该变量的其它文件则包含该变量的声明。

    C++primer推荐在使用变量的地方定义变量,并且在定义的时候最好初始化。也是贯彻他的那句使用变量之前最好先初始化。

const常量和引用一样,必须在定义时初始化。并且初始化之后就不能再修改其值和绑定的对象

    全局作用域中定义的非const变量可以在整个程序中访问,而const类型的变量仅仅可在定义它的文件内可见。所以可在不同的文件中对同const进行重复或不同定义。同时有时候为了使其具有全局作用域,可以在定义时添加extern声明全局性,如在文件1中有extern const int i=10;在文件2中可以声明extern const int i;来达到访问其他文件的const变量的目的。

    一旦一个引用绑定到一个对象,必须从一而终,不能再绑定到其他对象。这一点类似于 char * const p=&a;非const引用只能绑定到与该类型引用同类型的对象。而const引用还可以绑定到非const类型的对象上。没有引用的引用。

    int i=42;

    const  int &r=42;

    const int &r2=r+i;//int temp=r+i;实际r2绑定到temp,因为temp是无法修改的,此处r2必须是const类型的。

    头文件仅仅用于声明而不是用于定义,且会被包含在多个源文件中,因此用于定义的语句不应该放在头文件中。如extern int ival=10;double a;

对于头文件不应该含有定义这一规则,有三个例外:(并且他们也最好在头文件中定义)1:头文件可以定义类2:编译时就确定值const对象3:inline函数。这些实体可在多个源文件中定义,只要每个源文件中的定义是相同的。

    当我们在头文件中定义了const变量后,每个包含该头文件的源文件都有自己的const变量,其名称和值是一样。但不是一个。因为const变量默认的作用域是定义它的文件,因此各个文件定义自己的const变量是合法的。

    预处理器变量的名字在程序中必须是唯一的,我们可以使用类名为预处理器变量的名字来防止程序中预处理器变量重名的问题。

    前两个章节相对来知识点不多,但整个C++的面貌大体出现了,我感觉过多的概念导致前两章不太适合初学者阅读,过早的放弃这本书的人我相信在前两面前就已经撤了,毕竟七八百页不是一咬牙就能坚持下来的。其实这也是我认为这本书不太适合毫无基础的C++学习者的原因


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值