C++ Primer 学习笔记-基础知识(一)

来源:互联网 发布:免费花生壳顶级域名 编辑:程序博客网 时间:2024/06/14 02:12
目录

  • 头文件与命称空间
  • 变量与数据类型
    • 变量命名规则
    • 数据类型
    • 浮点数的优缺点
    • const 限定符
  • 复合类型
    • 数组
    • 字符串
    • string类
    • 结构体
    • 共用体
    • 枚举
    • 指针和自由存储空间

本文是复习C++的读书笔记之一,参考C++ Primer 前四章


头文件与命称空间

头文件:有些文件由“#include ”包含进其他文件,写在其他文件的头部,也叫头文件。
例如使用#include编译指令,#include <iostream> 该编译指令导致预处理器将iostream的文件内容添加到程序中。在源代码编译之前替换或者添加文本。

头文件命名约定

头文件类型 约定 范例 说明 C++旧式风格 以.h结尾 iostream.h C++程序可以使用 C旧式风格 以.h结尾 math.h C和C++程序都可以使用 C++新式风格 没有扩展名 iostream C++可以使用,使用namespace std 转换后的C 加上前缀c,没有扩展名 cmath C++可以使用,可以使用不是c的特性,如namespace std


命称空间:如上表使用iostream时需要使用名称空间编译指令 “using namespace std;”,叫做using 编译指令。省略using时,使用下面这种方式
std::cout<<”hello”<< endl;

变量与数据类型

变量命名规则

  • 名称中只能使用字母字符、数字和下划线
  • 名称的第一个字符不能是数字
  • 不能将C++关键字用作变量名称
  • 区分大小写字母
  • 长度没有限制,都有意义
  • 以两个下划线或者大写字母打头的名称被保留给实现(编译器及其使用的资源)使用
  • 以一个下划线打头的名称被保留给实现,用作全局标示符

    int Poodle; // valid but distinct from poodle
    int _Mytime; // valid but reserved –starts with underscore
    int __fools; // valid but reserved,starts with two underscore

数据类型

C++内置整型:unsigned int、int、unsigned short、short、unsigned long、long、unsigned char、char、bool;
C++内置浮点类型:float、double、long double

C++的基本整型有 char、short、int、long,每种类型有有符号和无符号两种,总共8种供选择。
char 一个字节8位
short 至少16位
int 至少与short相同
long 至少32位,且至少与int一样长

当前很多系统使用最小长度 short 16位 long32位 int 16、24或者32
C标准中并没有具体给出规定那个基本类型应该是多少字节数,而且这个也与机器、OS、编译器有关,比如同样是在32bits的操作系统系,VC++的编译器下int类型为占4个字节;而tuborC下则是2个字节。
使用sizeof()查看占用的字节数 通常short 2个字节 int 4个字节 long 4个字节 char 一个字节,有变化的一般是int和long,16位编译器int是2个字节,64位编译器long是8个字节,unsigned long: 8个字节

下面给出不同位数编译器下的基本数据类型所占的字节数:

32位编译器
short: 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 4个字节
long long: 8个字节
unsigned long: 4个字节

bool类型是ANSI/IOS C++标准添加的新类型


注意
cout<< hex不会显示任何内容,只是更改整型数值以16进制显示;由于hex位于命名空间std中,而程序使用了该命名空间,因此不能将它作为变量名,但是如果省略编译指令using,而使用std::cout, std::endl, std::hex, std::oct等等,则可以将它用作变量名。

#include<iostream>using namespace std;int main(){    int  num = 42;    cout<< num<<endl;    cout<<hex;    cout<<num<<endl;    cout<< oct;    cout<<num<<endl;} 

浮点数的优缺点

优点:

  • 可以表示整数之间的数值
  • 表示的范围较大

缺点:

  • 表示的精度降低
  • 运算速度比整数慢
#include <iostream>int main(){    using namespace std;    float a = 2.34E+22f;    float b = a + 1.0f;    cout<< "a = " << a << endl;    cout<< "b - a = " << b - a << endl;    return 0;}

程序输出:

a = 2.34E+022b - a = 0

输出 b - a = 0,因为float类型只能表示数值的前六位或者前七位,在23位加1,不会对表示的值的大小产生影响.

总结:

C++ 中 signed char、short、int、long统称为符号整型,他们的无符号类型称为无符号整型;bool、char、wchar_t、无符号整型和符号整型统称为整型;float、double和long double统称为浮点型;整型和浮点型统称为算数类型。

const 限定符

最好用const限定符定义符号常量,定义后不能修改,而不是使用C 中#define来定义
const int MONTHS = 12;
注意:
const int toes;//value of toes undefined
toes = 12; // too late
如果在声明常量时没有提供值,那么它的值将是不确定的,并且无法赋值改变。


复合类型

数组

有效下标的重要:
编译器不会检查使用的数组下标是否有效,如果将一个值赋值给一个不存在的下标的数组元素,编译器并不会指出错误,但是程序运行后可能会出现异常终止,也可能会破坏数据或代码

数组的初始化规则:
只有在定义数组的时候才能初始化数组,此后就不能使用了,也不能将一个数组赋值给另外一个数组。

int card[4] = {2, 3, 4, 5};  //正确int hand[4];   //正确hand[4] = {3,5,6,7};  //错hand = card;   //错 

不过可以使用下标分别给数组元素赋值。

字符串

C 风格的字符串以空字符结尾(null),字符数组中写作“\0
char dog[5] ={‘b’,’e’,’a’,’t’,’y’} not a string
char cat[5] ={‘c’,’e’,’a’,’t’,’y’,’\0’} a string
两个字符数组都是char数组,但只有第二个是字符串

C++很多处理字符串的函数,包括cout 都是逐个处理字符数组中的字符,知道遇到空字符后停止,如果cout显示的是上面的dog数组,cout打印5个字母,并接着将内存中随后的各个字节解释为要打印的字符,直到遇到空字符为止由于空字符在内存中很常见,因此会很快停止。但是,还是不应该将不是字符串的数组当字符串处理。

例如:
char fish[] = “sadhasa” 用引号括起来的字符串隐式的包括结尾的空字符,字符数组的长度要注意包括空字符。

“S”包含两个字符‘S’和‘\0’
‘S’;是83的一种写法

char aa = "S"  //不合法,“S”实际上表示的是字符串所在的内存地址,内存地址是一种独立的类型,不允许这样赋值char bb = 'S'  //合法

char boss[8] = “boss”;

b o s s \0 \0 \0 \0


strlen()函数返回的是存储在数组中的字符串的长度,而不是数组本身的长度。上面的数组长度是8,但是用strlen()函数返回的是字符串长度5

string类

std::string name = "Lijing";std::string name2 = name;

不能将一个数组赋给另一个数组,但是可以将一个string 赋给另一个string 对象

将一行输入读取到string str 对象:getline(cin, str);将一行输入读取到数组char charr[20] 对象:cin.getline(charr , 20);

结构体

创建结构包括两步:定义结构描述、创建结构变量

struct inflatable{    char name[20];    float volume;    double price;};inflatable hat; //C++ 允许省略struct关键字,但是C在此不能省略struct

使用成员操作符(.) 访问成员,如hat.volume

C++ 允许在声明结构变量时省略struct 关键字
C++的一些老版本不能对函数中定义的常规数组初始化,也不能对函数中定义的常规结构初始化,解决方式是加上static
某些编译器如7.0版本之前的Visual C++不支持String类对象作为成员的结构进行初始化

共用体

一种数据格式,能够存储不同的数据类型,但是只能同时存储其中的一种类型,也就是说结构可以同时存储int 、long 和double,但是共用体只能存储int、long或者double,也就是说共用体每次只能存储一个值

union one4all{    int int_val;    long long_val;    double double_val;};

可以使用one4all变量存储int、long或者double,但是条件是在不同的时间进行:

one4all pail;pail.int_val = 13;         //store int valuecout<<pail.int_val ;pail.double_val= 16.35;     //store double value, lost int value;cout<<pail.double_val;

用途:当数据项使用两种或更多种格式,但是不会同时使用的时候,可以节省空间。

struct  widget {    char band[20];    int type;    union id    {        long id_num;      //一些商品的id为long        char id_char[20]; //一些商品的id为char    }id_val;};....widget price;...if(price.type = 1){    cin>> price.id_val.id_num;}else{    cin>>price.id_val.id_char;}

枚举

C++的enum提供了另外一种创建符号常量的方式:

enum epecturm  = {red,orange,yellow,green,blue,violet};

可以用枚举名声明这种类型的变量;

epecturm  band

在不进行强制类型转换的情况下,只能将定义枚举时使用的枚举量赋值给这种枚举的变量,如下:

band = red;   //rightband = 233;   //wrong    233 is not a emuerator , 非enum值赋给enum 错误

枚举量是整型,可以被提升为int类型,但是int类型不能自动转换成枚举类型;

color = 3 + red; //right

对于枚举只定义了赋值运算,并没有为枚举定义算术运算

int color = blue;  //right++band; //wrongband = red+orange;// wrong    red + orange 将被转换为0+1,但是结果是一个int值不能赋值给band

枚举变量的取值与取值范围:
取值必须是整数

enum bitstep{first, second = 100, third};

first默认为0,third为101;
取值范围是0—127,因为最大值101,在2的幂中比这个大的最小值是128.

enum bit{one = -6, second = 9, third};

取值范围是-7—15,因为最小值101,在2的幂中比这个大的最小值是8. 8-1=7,加上负号-7

enum {zero, null= 0, one, number_tr = 1};

zero为默认值0,one和number_tr都是1

选择多少空间存储enum由编译器决定,对于取值范围较小的枚举,使用一个字节或者更小的空间;对于包含long类型的枚举,使用4个字节

指针和自由存储空间

指针的危险:

long   *fellow*fellow = 12993

上述代码没有赋给fellow一个地址,由于fellow没有被初始化,他可能是任何值,fellow指向的地方可能并不是要存储12993的地方,可能导致一些最隐匿、最难以跟踪的bug

一定要在指针应用*之前,将指针初始化一个确定的、适当的地址。这是关于使用只指针的金科玉律。

使用new 来分配内存,有可能因为内存不足分配失败,返回空指针

配对使用new 和delete,否则将发生内存泄漏

  • 只能用delete释放有new分配的内存,不过对空指针使用delete是安全的,不能使用delete释放声明变量所获得的内存。
int *ps = new int;  //allocate memory with new*ps = 198;...delete ps;   //free memory with delete
  • 不要尝试释放已经释放过的内存块,否则可能发生预想不到的情况

  • 不要创建两个指向同一个内存块的地址,因为这样将会增加删除同一个内存块两次的机会,出现意想不到的情况

  • 如果使用new []创建数组,那么对应的使用delete []来释放

int *thirst = new int [10];...delete [] thirst;   //free a dynamic array

使用动态数组

#include<iostream>using namespace std;int main(){    double *member = new double[3];     member[0] = 19;    member[1] = 22;    member[2] = 33;    cout<<"*member is "<< *member<<endl;    cout<<"member[1] is"<<member[1]<<endl;    member = member + 1;    cout<<"Now member[0] is"<<member[0]<<endl;    cout<<"and member[1] is "<<member[1]<<endl;"    member = member - 1;  // point back to begining    delete [] member;     // free memory    return 0;}

将member减去1,才能让它指向最开始的位置,这样delete删除时才正确

将指针变量加1后,其增加的值等于指向的类型占用的字节数

一般来说C++中数组名被视为数组中的第一个元素的地址
可以修改指针的值,但是数组名是常量,不能修改数组名的值

pointername = pointername + 1;  //allowedarrayname = arrayname +1;  //not allowed
数组的动态联编:使用new关键字创建的数组,在运行时为数组分配空间,长度也将在运行时设置,使用完用delete释放数组的静态联编:使用数组声明来创建数组时,数组的长度在编译时设置。

自由存储空间:

c++有三种管理数据存储的方式,自动存储、静态存储和动态存储(有时也叫自由存储空间或者堆);

自动存储:

局部变量的存储位置

静态存储:

静态存储是在整个程序执行期间都存在的存储方式,有两种:函数外定义和声明时使用static

动态存储:

new 创建的变量,允许在一个函数中创建分配内存,在另外一个函数中释放;数据的生命周期就不完全受到程序或函数的生存时间控制。 
原创粉丝点击