有时候怀疑真是怀疑自己走的路究竟是不是正确的。作为一个土生土长数学系学生,却对数学毫无兴趣,没事的时候就喜欢躲在图书馆看看有关计算机的书。有时候期末考试时候会挂个一两门的数学专业课,有时候真希望数学课本上这一个个繁琐的证明是用代码写的。自己差点儿丢掉了本专业的一切。去全身心投入到计算机这一庞大而繁琐的学问中去。
真心不知道2年之后自己毕业,自己的结果究竟是什么样的。自己如今唯一能做而又不让自己懊悔的我想就是尽可能的多学两门语言与多看几本计算机上的名著了。有时候真的不确定自己会坚持到什么地步,是一直的走下去,还是。
。。哎,先不纠结了,默默的坚持下去吧,坚持自己喜欢的东西。假设自己一直在数学的道路走下去的话。可能会生不如死。。
。
3.1 数组的替代品 模板类array
vector类的功能比数组强大,可是付出的代价是效率稍低。假设您须要长度固定的数组,使用数组是最佳的选择。但代价是不那么方便和安全。
有鉴于此。C++新增了模板类array。
与数组一样array对象的长度也是固定的。也使用栈。而不是自由存储区,因此效率与数组同样
#include<array> ... using namespace std; array<int,5>ai; array<double,4>ad={1.2,2.1,3.43.4.3}; //推而广之 array<typename,n_element>array;
3.2 比較数组、vector对象和array对象
以下来看一个简单的演示样例
#include<iostream> #include<vector> #include<array> int main() { using namespace std; double a1[4]={1.2,2.4,3.6,4.8}; vector<double>a2(4); a[0]=1/3; a[1]=2/3; a[3]=3/4' a[4]=4/5; array<double,4>a3={3.14,2.72,1.62,1.41}; array<double,4>a4; a4=a3;//能够直接复制,差别于数组 cout<<"a1[2]:"<<a1[2]<<"at"<<&a1[2]<<endl; cout<<"a2[2]:"<<a2[2]<<"at"<<&a2[2]<<endl; cout<<"a3[2]:"<<a3[2]<<"at"<<&a3[2]<<endl; cout<<"a4[2]:"<<a4[2]<<"at"<<&a4[2]<<endl; return 0; }
首先。注意到不管是数组还是vector对象和array对象,都能够使用标准数组表示法来訪问各个元素。其次从地址可知,array对象和数组存储在同样的内存区域(栈)中,而vector则存储在还有一个区域中。自由存储区或堆中。第三,注意到能够将array对象赋给还有一个array对象;而对于数组,必须逐个复制元素。
3.3 副作用和顺序点
首先副作用指的是计算表达式时对某些东西进行了改动。顺序点是程序运行的一个点。在这里。进去下一步之前将确保对全部的副作用进行评估。在C++中,语句中的分号就是一个顺序点,这意味着程序在处理下一个语句之前,赋值运算符、递增运算符和递减运算符运行的全部改动都必须完毕。另外不论什么完整的表达式末尾都是一个顺序点。
什么是一个完整的表达式呢?他是这种:不是还有一个更大表达式的子表达式。以下来通过两个样例来加深一下理解
while(guests++<10) cout<<guests<<endl; //在这里表达式guests++<10是一个完整的表达式,由于它是while循环的測试条件,因此该表达式末尾是一个顺序点 y=(4+x++)+(6+x++); //表达式4+x++不是一个完整的表达式,因此不能保证计算子表达式4+x++后立马添加。在这里整条赋值语句才是一个完整的表达式。并且分号表示了顺序点,所以在这里仅仅保证在运行下一条语句之前才会将X添加两次。
3.4 递增/递减和指针
当我们同一时候将*与++同一时候用于指针时将有这种疑问:将什么解引用,将什么递增。
这取决与优先级和运算符的位置。前缀递增、前缀递减和解除引用运算符的优先级同样。后缀递增与后缀递减的优先级同样,但比前缀运算符的优先级高,这两个运算符从左到右的方式进行结合。
- 前缀运算符从右向左结合规则意味着*++p的含义例如以下:先将++应用于pt,然后将*用于被递增后的pt。
还有一方面,++*p意味着先去得pt指向的值。然后将这个值加一。
- 接下来请看以下的组合(*pt)++。圆括号指出首先对指针解除引用。然后再将这个值递增。
- 最后再看下这个组合。x=*pt++;后缀运算符++的优先级更高,这意味着将运算符用于pt,而不是*pt。
3.5 复合语句(语句块)
语句块就是用一对花括号括起来的一条复合语句。他被视作一条语句。从而满足句法的要求。比方for循环:
for(int i=1;i<=5;i++) { cout<<"Value"<<i<<":"; cin>>number; sum+=number; }复合语句另一条有趣的性质。假设在语句块中定义一个新的变量,则仅当程序运行该语句块时,该变量才存在。运行完语句块后该变量将被释放。假设在一个语句块中声明一个变量,而在外部语句中也有一个这种变量,情况将怎样呢?在声明位置到内部语句结束的范围内,新变量将隐藏旧变量;然后旧变量再次可见。例如以下例所看到的:
#include<iostream> int main() { using namespace std; int x=20; { cout<<x<<endl; int x=100; cout<<x<<endl;//use new x } cout<<x;// use original x return 0; }
3.6 C-风格字符串与string类字符串的比較
首先讨论下C-风格字符串。
因为C++将C-风格字符串视为地址。因此假设以关系运算符来比較它们将无法得到惬意的结果。相反,应使用C-风格字符串库中的strcmp()函数。该函数接受两个字符串地址作为參数,这意味着參数能够是指针、字符串或是数组名。
以下着重介绍一下string类字符串的比較。
它的比較比較简单。由于类设计可以让您使用关系运算符进行比較。这之所以可行是由于类函数重载了这些运算符。来看例如以下样例:
#include<iostream> #include<string> int main() { using namespace std; string word="?ate"; for(char ch='a';word!="mate";ch++) { cout<<word<<endl; word[0]=ch;//用数组的方法来提取当中的字符 } cout<<"After loop ends,words is"<<wrd<<endl; return 0; }
- string类重载运算符!=的方式能够让您在下述条件下使用它:至少有一个操作数为string类对象,还有一个操作数能够是string类,也能够是C-风格字符串。
- string类的设计能够将其作为一个实体,也能够将其作为一个聚合对象。从而用数组的方法来提取当中的字符。
有时候延时一段时间非常实用。比方,读者可能遇到这种程序。它在屏幕上显示一条消息,而还没来得及阅读,又出现了其它的内容。C++库中有一个函数有助于完毕这种操作。这个函数名为clock。返回程序開始运行后所用的系统时间。这有两个复杂的问题:clock()返回的不一定是秒;其次该函数的返回类型可能不确定。
为解决这种问题,在头文件ctime提供了这种解决方式。首先它定义了一个符号常量--CLOCK PER SEC。该常量等于每秒钟包括系统时间的单位数。因此将系统时间除以这个数能够得到秒数。
或者将这个数乘上CLOCK PER SEC。能够得到以系统时间为单位的单位时间。其次。ctime将clock_t作为clock()返回类型的别名。例如以下程序演示了怎样使用clock()函数和ctime头文件来创建延时循环:
#include <iostream> #include <ctime> using namespace std; int main() { cout<<"Enter the delay time,in seconds:"; float seconds; cin>>seconds; clock_t delay=seconds*<strong>CLOCKS_PER_SEC</strong>; cout<<"startinga "; clock_t start=clock(); while(clock()-start<delay) ; cout<<"Donea "; return 0; }
3.8 类型别名
以下简要介绍一下类型别名。C++为类型创建别名有两种方式。
一种是使用预处理器:
#define BYTE char这样,预处理器将在编译程序编译程序是用char来替换BYTE,从而使BYTE成为char的别名。
另外一种方法使用keywordtypedef来创建别名。完毕上述的代码能够
typedef char BYTE; typedef typeName aliaName//通用格式普通情况下最好使用typedef来声明一系列的变量。而在使用#define时可能会遇到一些问题。注意,typedef不会创建新类型,而仅仅是为已有的类型创建一个别名,在有些情况下,在定义一些变量时会更简便。