读书笔记
1.1 $ 开始介绍
g++ prog1.cc -o prog1
1.2 输入输出
iostream 库的基础是两种命名为 istream 和 ostream 的类型,流是指要从某种 IO 设备上读入或写出的字符序列.
运行程序时,大部分操作系统都提供了重定向输入或输出流的方法。利用重定向可以将这些流与所选择的文件联系起来。
1.44 读入未知数目的输入
while (std::cin >> value),一直读数直到程序输入结束,while 条件测试输入操作符的返回结果,意味着测试 std::cin,如果流是有效的(也就是说,如果读入下一个输入是可能的)那么测试成功。遇到文件结束符或遇到无效输入时,如读取了一个不是整数的值,则 istream 对象是无效的。处于无效状态的 istream 对象将导致条件失败。
part1 基础知识
和大多数程序设计语言一样,C++ 中对象的类型决定了该对象可以执行的操作。语句正确与否取决于该语句中对象的类型。一些程序设计语言,特别是 Smalltalk 和 Python,在运行时才检查语句中对象的类型。相反,C++ 是静态类型(statically typed)语言,在编译时执行类型检查。结果是程序中使用某个名字之前,必须先告知编译器该名字的类型。
C++ 提供了一组内置数据类型、操纵这些类型的操作符和一组少量的程序流控制语句。这些元素形成了一个“词汇表”,使用这个词汇表可以而且已经编写出许多大型、复杂的实际系统。从这个基本层面来看,C++ 是一门简单的语言。C++ 的表达能力是通过支持一些允许程序员定义新数据结构的机制来提升的。
2.1基本内置类型
C++ 定义了一组表示整数、浮点数、单个字符和布尔值的算术类型,另外还定义了一种称为 void 的特殊类型。void 类型没有对应的值,仅用在有限的一些情况下,通常用作无返回值函数的返回类型。
算术类型的存储空间依机器而定。这里的存储空间是指用来表示该类型的位(bit)数。C++标准规定了每个算术类型的最小存储空间,但它并不阻止编译器使用更大的存储空间。事实上,对于int类型,几乎所有的编译器使用的存储空间都比所要求的大。int表 2.1 列出了内置算术类型及其对应的最小存储空间。
2.2
练习:2.1,int、long 和 short 类型之间有什么差别? 类型不同,所占位数(字数不同),都是整形. (它们的最小存储空间不同,分别为16,32,16.short为半个机器字,int为一个机器字,long为一个和2个,32位机器中,int和long一样字长)
2.36 作用域
int bb = 5;
for(int bb=1;bb<5;bb++)
{
}
//cout<<bb<<endl; //ERROR bb被覆盖,并且在for中,并认为是语句作用域中的变量,只能自for中使用
2.4 const
在全局作用域(第 2.3.6 节)里定义非 const 变量时,它在整个程序中都可以访问。我们可以把一个非 const 变更定义在一个文件中,假设已经做了合适的声明,就可在另外的文件中使用这个变量:
// file_1.cc
int counter; // definition
// file_2.cc
extern int counter; // uses counter from file_1 使用前的声明
++counter; // increments counter defined in file_1
与其他变量不同,除非特别说明,在全局作用域声明的 const 变量是定义该对象的文件的局部变量。此变量只存在于那个文件中,不能被其他文件访问。
// file_1.cc
// defines and initializes a const that is accessible to other files
extern const int bufSize = fcn(); 定义初始化时加上extern表明外部可以用,
// file_2.cc
extern const int bufSize; // uses bufSize from file_1 声明
// uses bufSize defined in file_1
for (int index = 0; index != bufSize; ++index) 使用
// ...
看来extern不是只用在声明,因为非 const 变量默认为 extern。要使 const 变量能够在其他的文件中访问,必须地指定它为 extern。
const定义时 必须给出初始值
const引用,是指向const对象的引用,
const int val =20; const int &ref = val; int &bb = val(错误,必须
const引用指向const对象) (val不能修改,ref也不能修改)
cout<<"----------next-----------"<<ends;*/
int const ii = 5;
int jj= ii; //const常量值,可以赋值给普通变量
cout<<jj<<endl;
4.1 数组
1) 数组的长度是固定的,而且数组没有办法知道给定数组的长度,没有能够获取其容量的size操作,也不能pushback添加元素. 如果要更改数组的长度,程序员只能创建一个更大的数组,然后把原数组所有元素cp到新数组中. 整形数组大小:sizeof(数组名)/sizeof(数组类型)。字符数组大小:strlen(数组名)+1,1因为要加上'/0',所以再加1.
2) 数组的定义
数组的初始化 (函数内/外)
3)vector怎么也要遍历后才能确认2者是否相等,不能直接用 == 么? vector不允许类似数组的花括号形势定义赋值.
4.2 指针
1) void* 的意思,表明该指针和一地址值有关,但是不清楚该地址上的对象的类型.不允许void指针操纵它所指向的对象,可以通过它给另外一个void*指针赋值,可以与另外指针比较,可以向函数传递和返回vodi*,可以让其他指针赋值给void*.
2) 指针的0, NULL其实一样.
3) 可以给指针赋值为 字面常量0或者常量表达式结果为0的. 如int *p =0, const int i =0; int*p = i;
4) 现在的编译器无法确定一个指针是否指向一个有效对象,因为现在无法确认一个指针是否初始化,不确定它指向一个有效的地址呢,还是指向的存储空间是不是存放的不确定的二进制位形成的地址.不同类型的指针不能赋值给另外一个类型的指针, 如int不能给long 等.
5) 指针和引用. *p1=&a; *p2=&b; p1=p2,修改的是指针的值,它们以前指向的值都不变.
&p1=a; &p2=b; p1=p2; 修改的是a,, a被赋值成b了. 引用都没变.
引用必须开始就初始化.
6) 指向const对象的指针
/*int i = 3;
const int *p = &i;
i=4; //okey i本身可以修改, 但是由于p为指向const对象的指针, 那么不能通过p来修改i 即使i不是const,也不能通过p来修改
*p = 4;//error
*/
如果i为const,那么p必须是const 不然报错
/*const int i = 3;
int *p = &i; //报错
*/
const指针 int *const pp = &i; 记住 int const *pp不是const指针,而是指向const对象的指针 (要看*修饰符是不是在const前\后)
例子:
//const指针
int i=5,j=6;
int *const p = &i;
//int const *p=&i; 这和const int *p一样
p=&j; //const指针不能改 *p=6 可以
cout<<*p<<endl;
typedef在指针上的用法
typedef string* pstring;
const pstring cstr; //一定要记住,const是修饰cstr的,真实意思是 string *const cstr; 而不是 const string* cstr;
// 其实如果 后者pstring const cstr这样写是同义的. const都是修饰的为变量, 仔细阅读const的声明,
// 就会知道,const限定符都可以放在类型的前面和后面都一样的.
const int *p 可以不初始化,但是使用p时要初始化.而int *const p的话,需要一开始就初始化,因为p为const指针.前者是指向const对象的指针
7) c风格字符串
char pp[] = {'1','2'}, char *p = pp; 这2个是字符数组,后者是指向数组的指针.
char pp[] = {'1','2','\0'}, char *p = "22" <==> const char *p = "22"
判断字符串结束 用 while(*pp) {},, 用while(pp)不准确,因为pp为null的情况,不确定.
c风格字符串和string字符串比较,后者版本更短,更容易理解,出错几率小.
8) 动态数组,
const动态数组必须初始化,加()
如果我们在自由存储区中创建的数组存储了内置类型的 const 对象,则必
须为这个数组提供初始化:因为数组元素都是 const 对象,无法赋值。实现这
个要求的唯一方法是对数组做值初始化:
// error: uninitialized const array
const int *pci_bad = new const int[100];
// ok: value-initialized const array
const int *pci_ok = new const int[100]();
C++ 允许定义类类型的 const 数组,但该类类型必须提供默认构造函数:
// ok: array of 100 empty strings
const string *pcs = new const string[100];
在这里,将使用 string 类的默认构造函数初始化数组元素。
当然,已创建的常量元素不允许修改——因此这样的数组实际上用处不大。
允许动态分配空数组. new char[0]; 这个用new创造的长度为0的数组时,new返回有效的非空非null指针.但是这个指针不能解引用操作,毕竟
它没有指向任何元素,它允许的操作包括 : 比较运算,+ - 0, -本身. 可以引用在循环中,
new后面的长度可以由表达式/函数动态获得, 如 int i = getVal(); char* pp = new char[i];
1. delete pa[] ; 释放是delete[] pa;
2, vector<int> vint ;
cin>>vint;
int *p = new int[vint.size()];
for(int i - vint.length(0)
p[i] = vint(i);
3,
4, char *p = "hello"; char* pp = "world";
strcpy();
关于size()和length
sizeof可以计算一个类型的大小空间 length只是针对字符串而言的 标准c里没有length这个函数 只有在C++中的string类中才有length这个函数在这里还要介绍下strlen.sizeof("abcd")的值为5length("abcd")的值为5strlen("abcd")的值为4,不计算后面的'\0'
char* 和string , 右边可以给左边赋值,可以使用 C 风格字符串对 string 对象进行初始化或赋值。string 类型的加法操作需要两个操作数,可以使用 C 风格字符串作为其中的一个操作数,也允许将 C 风格字符串用作复合赋值操作的右操作数。 但是反之不行, 但可以通过c_str()折中赋值,但是如果c_str()返回的指针是指向const char类型的数组的话,那么就需要 const char *str = st2.c_str(); // ok, 这样最保险.
9) 怎么通过vector复制数组.