C++学习笔记1-C++基础
记录
温故而知新
文章目录
C++学习书目推荐
[0]The c++ programming language ----Bjarne Stroustrup ,技术权威,用词深峻,思想深远,c++百科全书代表,圣经。
[1]c++ Primer ----stanly lippman—纵横书市十数年,c++最佳教本,c++百科全书代表。
[2] Effective c++ -----通过50个编程实例,展示专家经验,行文有趣,深处浅出。
[3] More Effective c++ -----通过35个编程实例,展示专家经验,行文有趣,深处浅出。
[4] c++ standard library -----c++标准库的百科全书。
机器语言与汇编语言
机器语言
CPU能直接执行的唯一语言。
汇编语言
面向机器的语言,低级语言。
汇编语言介绍
一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。在汇编语言中,用助记符代替机器指令的操作码,用地址符号或标号代替指令或操作数的地址。在不同的设备中,汇编语言对应着不同的机器语言指令集,通过汇编过程转换成机器指令。普遍地说,特定的汇编语言和特定的机器语言指令集是一一对应的,不同平台之间不可直接移植。
驱动程序、嵌入式操作系统和实时运行程序都需要汇编语言。
C++语法
头文件
#include<iostream>
不是C++的语句,是C++的一个预处理命令,它以#开头以与C++语句相区别,行的末尾没有分号。作用是将文件iostream的内容包含到该命令所在的程序文件中,代替该命令行。
include:单词意思包含
文件包含
所谓文件包含处理是指一个源文件可以将另外一个源文件的全部内容包含进来,即将另外的文件包含到本文件之中。
C++提供了#include命令用来实现文件包含的操作。
如在file1.cpp中有以下#include命令:
#include ″file2.cpp″
“文件包含”命令是很有用的,它可以节省程序设计人员的重复劳动。
库函数的开发者把这些信息写在一个文件中,用户只需将该文件“包含进来即可(如调用数学函数的,应包含cmath文件),这就大大简化了程序,写一行#include命令的作用相当于写几十行、几百行甚至更多行的内容。
文件包含的功能
不同的头文件包括以上不同的信息,提供给程序设计者使用,这样,程序设计者不需自己重复书写这些信息,只需用一行#include命令就把这些信息包含到本文件了,大大地提高了编程效率。由于有了#include命令,就把不同的文件组合在一起,形成一个文件。因此说,头文件是源文件之间的接口。
文件包含一般包含那些文件
这种常用在文件头部的被包含的文件称为标题文件”或“头部文件”。
头文件一般包含以下几类内容:
(1) 对类型的声明。
(2) 函数声明。
预处理
程序设计语言的预处理的概念:在编译之前进行的处理。
文件包含两种方式的区别
都是合法的。二者的区别是: 用尖括号时,系统到系统目录中寻找要包含的文件,如果找不到,编译系统就给出出错信息。
有时被包含的文件不一定在系统目录中,这时应该用双撇号形式,在双撇号中指出文件路径和文件名。
**如果在双撇号中没有给出绝对路径,如#**include ″file2.c″则默认指用户当前目录中的文件。系统先在用户当前目录中寻找要包含的文件,若找不到,再按标准方式查找。如果程序中要包含的是用户自己编写的文件,宜用双撇号形式。
C++标准库
• 在C++编译系统中,提供了许多系统函数和宏定义,而对函数的声明则分别存放在不同的头文件中。
• C++的库除了保留C的大部分系统函数和宏定义外,还增加了预定义的模板和类。
• 新的C++标准库中的头文件一般不再包括后缀.h
,例如#include <string>
为使已有的C程序能继续运行,许多C++编译系统保留C的头文件,即提供两种不同的头文件,由程序设计者选用。如
#include <iostream.h> //C形式的头文件
#include <iostream> //C++形式的头文件
效果基本上是一样的。建议尽量用符合C++标准的形式,如果用户自己编写头文件,用.h
为后缀。
C++程序从编写到运行要经历那些过程
1. 用C++语言编写程序
用高级语言编写的程序称为“源程序” 。C++的源程序是以.cpp作为后缀。
2. 对源程序进行编译
编译:用一种称为编译器(complier)”的软件,把源程序翻译成二进制形式的“目标程序(object program)”,以.obj
作为后缀。
编译的作用是对源程序进行词法检查和语法检查。并给出的出错信息,一种是错误(error);一种是警告(warning)
3. 将目标文件连接
用系统提供的“连接程序(linker)”将一个程序的所有目标程序和系统的库文件以及系统提供的其他信息连接起来,最终形成一个可执行文件,它的后缀是.exe
。
4. 运行程序
运行最终形成的可执行的二进制文件(.exe
文件),得到运行结果。
5. 分析运行结果
如果运行结果不正确,应检查程序或算法是否有问题。
包含类的C++程序
#include <iostream> // 预处理命令
using namespace std;
class Student // 声明一个类,类名为Student
{
private: // 以下为类中的私有部分
int num; // 私有变量num
int score; // 私有变量score
public: // 以下为类中的公用部分
void setdata( ) // 定义公用函数setdata
{cin>>num; // 输入num的值
cin>>score; // 输入score的值
}
}
输入输出
cin智能输入
cin>>a //注意行末尾无分号
>>b //这样写可能看起来清晰些
>>c
>>d;
//也可以写成:
cin>>a;cin>>b;cin>>c;cin>>d;
**以上3种情况均可以从键盘输入:
1 2 3 4
**也可以分多行输入数据:
1
2 3
4
cin输入的特点
cin输入时,系统根据变量的类型从输入流中提取相应长度的字节
不能用cin语句
把空格字符和回车换行符作为字符输入给字符变量,它们将被跳过。
在输入流数据时,按照cin语句中变量的类型的格式输入,否则容易出错。
在输入输出流使用控制符
• 直接使用cout和cin时采用默认格式输入输出。
•C++提供了在输入输出流控制符实现输入输出的格式控制。***如在输出实数时规定字段宽度,只保留两位小数,数据向左或向右对齐等。
•使用控制符头文件:#include<iomanip>
历史原因
在标准C++以前,都是用#include<iostream.h>这样的写法的,因为要包含进来的头文件名就是iostream.h。标准C++引入了名字空间的概念,并把iostream等标准库中的东东封装到了std名字空间中,同时为了不与原来的头文件混淆,规定标准C++使用一套新的头文件,这套头文件的文件名后不加.h扩展名,如iostream、string等等,并且把原来C标准库的头文件也重新命名,如原来的string.h就改成cstring(就是把.h去掉,前面加上字母c),所以头文件包含的写法也就变成了#include 。
并不是写了
#include<iostream>
就必须用using namespace std;我们通常这样的写的原因是为了一下子把std名字空间的东东全部暴露到全局域中(就像是直接包含了iostream.h这种没有名字空间的头文件一样),使标准C++库用起来与传统的iostream.h一样方便。如果不用using namespace std;使用标准库时就得时时带上名字空间的全名,如
std::cout << "hello" << std::endl;
使用stew
如果在多个cout语句中使用相同的(n),并使用
setiosflags(ios∷right);
可以实现各行数据右对齐,如果指定相同的精度,可以实现上下小数点对齐
常变量
常变量**:定义变量时**,加上关键字const**,则变量的值在程序运行期间不能改变**,故又称为只读变量
const int a=3;
说明:
1.在定义常变量时必须同时对它初始化(即指定其值),此后它的值不能再改变。
2常变量不能出现在赋值号的左边。
const int a;
a=3; //错误//常变量不能被赋值
**3.**可以用表达式对常变量初始化
const int b=3+6,c=3*cos(1.5)
区分符号常量和常变量
区别
- #define定义的符号常量, const定义的常变量
1.符号常量是用一个符号代替一个字符串,在预编译时做字符串替换,无类型,不分配内存。
2.常变量具有变量的特征,有类型**,在内存中分配存储单元**,可以用sizeof运算符测出其长度,但其值不能**改变
3. #define命令定义常量是C中的**方法,C++保留以便和C兼容。C++中习惯用const定义常变。
4.虽然二者实现的方法不同,但从使用的角度看,都可以认为用了一个标识符代表了一个常量。但本质上存在区。
const常变量可以改做为函数参数,从而保证实参数据不被修改的安全性
函数重载
重载函数的参数个数、参数类型或参数顺序3者中必须至少有一种不同,函数返回值类型可以相同也可以不同
即参数列表不同!
函数模板
函数模板**(functiontemplate):建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表。这个通用函数就称为函数模板**。
定义函数模板的一般形式为
template < typename T> 或template <class T>
通用函数定义
其中为虚拟类型
说明:
1.函数体相同的函数都可以用这个模板来代替,不必定义多个函数,只需在模板中定义一次即可。
2.在调用函数时系统会根据实参的类型来取代模板中的虚拟类型,从而实现了不同函数的功能。
**3.**类型参数可以不只一个,可以根据需要确定个数。如
template <class T1,typename T2>
4.用函数模板比函数重载更方便,程序更简洁。
5. 它只适用于函数的参数个数相同而类型不同,且函数体相同的情况,如果参数的个数不同,则不能用函数模板。
函数模板调用方式
当参数列表中1+个参数时
调用形式: 函数名(参数列表);
即不需要显式给出具体的数据类型
2:当函数里无参数列表时
调用形式: 函数名<基础类型名>();
即必须显式给出数据类型,否则编译系统无法推断虚拟类型的具体类型是什么。
代码案例
#include <iostream>
using namespace std;
template<typename T> //模板声明,其中T为类型参数
T max(T a,T b,T c) //定义一个通用函数,用T作虚拟的类型名
{if(b>a) a=b;
if(c>a) a=c;
return a;
}
int main( )
{int i1=185,i2=-76,i3=567,i;
double d1=56.87,d2=90.23,d3=-3214.78,d;
long g1=67854,g2=-912456,g3=673456,g;
i=max(i1,i2,i3); //调用模板函数,此时T被int取代
d=max(d1,d2,d3); //调用模板函数,此时T被double取代
g=max(g1,g2,g3); //调用模板函数,此时T被long取代
cout<<″i_max=″<<i<<endl;
cout<<″f_max=″<<f<<endl;
cout<<″g_max=″<<g<<endl;
return 0;
}
无参数模板函数的使用
#include<iostream>
using namespace std;
template<typename T>
T input()
{T cin>>a; return a;}
int main()
{
int a=input<int>();
cout<<a<<endl;
return 0;
}
函数定义注意
(1) 如果函数的定义在函数调用之前,则应在函数定义中给出默认值。如果函数的定义在函数调用之后,则在函数调用之前需要有函数声明,此时必须在函数声明中给出默认值,在函数定义时可以不给出默认值。
**(2) **一个函数不能既作为重载函数,又作为有默认参数的函数。因为当调用函数时如果少写一个参数,系统无法判定是利用重载函数还是利用默认参数的函数,出现二义性,系统无法执行。
内置函数
在编译时将所调用函数的代码直接嵌入到主调函数中,而不是将流程转出去。这种嵌入到主调函数中的函数称为内置函数(inline function),又称内嵌函数。在有些书中把它译成内联函数。
指定内置函数的方法很简单,只需在函数首行的左端加一个关键字inline即可。
定义方式
(1)可以在声明函数和定义函数时同时写inline,也可以只在其中一处声明inline
(2)使用内置函数可以节省运行时间,但却增加了目标程序的长度。因此一般只将规模很小而使用频繁的函数**声明为内置函数
(3)对函数作inline声明,只是程序设计者对编译系统提出的一个建议,即是建议性的,而非指令性的。并非一经指定为inline,编译系统就必须这样做。编译系统会根据具体情况决定是否这样做。
归纳起来,只有那些规模较小而又被频繁调用的简单函数,才适合于声明为inlin函数。
引用
引用:是为一个变量起一个别名
int a; //定义a是整型变量
int &b=a; //声明b是a的引用
a,b代表同一变量。
(1)在声明引用类型变量时进行初始化,即声明它代表哪一个变量。
(2)在声明变量b是变量a的引用后,b不能再作为其他变量的引用(别名)。
int a1,a2;
int &b=a1;
int &b=a2; //企图使b又变成a2的引用(别名)是不行的
引用作为函数参数
引用主要用于作为函数参数,以扩充函数传递数据的功能。
函数参数传递的三种情况。
(1)将变量名作为实参和形参。
值传递,单向传递。形参值的修改不会修改实参的值,因为形参和实参不是同一个存储单元。
(2)传递变量的指针。
形参是指针变量,实参是一个变量的地址,调用函数时,形参(指针变量)指向实参变量单元。
引用形参与指针形参的区别
(1)不用另外开辟内存
(2)系统向形参传送的是实参的地址而不是实参的值,但引用作形参时,实参的形式直接是变量名。
(3)引用的用法比使用指针变量简单、直观、方便。
(4)使用变量的引用,可以部分代替指针的操作。过去只能用指针来理的问题,可以用引用来代替,降低了程序设计的难度。
字符串
字符串比较
可以直接用 ==(等于)、>(大于)、<(小于)、!=(不等于)、>=(大于或等于)、<=(小于或等于)等关系运算符来进行字符串的比较。
字符串数组
(1) 在一个字符串数组中包含若干个元素,每个元素相当于一个字符串变量。
(2) 并不要求每个字符串元素具有相同的长度,即使对同一个元素而言,它的长度也是可以变化的,当向某一个元素重新赋值,其长度就可能发生变化。
(3) 在字符串数组的每一个元素中存放一个字符串,而不是一个字符。一个一维字符数组存放一个字符串
(4) 每一个字符串元素中只包含字符串本身的字符而不包括′\0′。**
字符串数组怎样给数组元素分配存储空间
编译系统为每一个字符串变量分配16个字节,在这个存储单元中,不直接存放字符串本身,而存放字符串的地址。
在字符串变量中存放的是字符串的指针.
布尔类型
在编译系统处理逻辑型数据时,将false处理为0,将true处理为1,逻辑型数据可进行算术运算。
一个非零数值赋给逻辑型变量,按真处理,如
bool flag=123; //赋值后flag的值为true
cout<<flag;
动态分配和撤销内存的运算符new和delete
在软件开发过程中,常常需要动态地分配和撤销内存空间,例如对动态链表中结点的插入与删除。在C语言中是利用库函数malloc和free来分配和撤销内存空间的。
C++提供了较简便而功能较强的运算符new和delete来取代malloc和free函数。
注意,new和delete是运算符,不是函数,因此执行效率高。
new int; //开辟一个存放整数的存储空间,返回一个指向该存储空间的地址(即指针)
案例代码
int *p=(int *)malloc(sizeof(int));
*p=9;
cout<<*p<<endl;
free(p);
new运算符
new运算符使用的一般格式为
new 类型 (初值)
用new分配数组空间时不能指定初值。
如果由于内存不足等原因而无法正常分配空间,则new会返回一个空指针NULL,用户可以根据该指针的值判断分配空间是否成功。
要访问用new所开辟的结构体空间,无法直接通过变量名进行,只能通过指针p进行访问。
对动态链表中结点的插入与删除。在C语言中是利用库函数malloc和free来分配和撤销内存空间的。
C++提供了较简便而功能较强的运算符new和delete来取代malloc和free函数。
注意,new和delete是运算符,不是函数,因此执行效率高。
new int; //开辟一个存放整数的存储空间,返回一个指向该存储空间的地址(即指针)
案例代码
int *p=(int *)malloc(sizeof(int));
*p=9;
cout<<*p<<endl;
free(p);
new运算符
new运算符使用的一般格式为
new 类型 (初值)
用new分配数组空间时不能指定初值。
如果由于内存不足等原因而无法正常分配空间,则new会返回一个空指针NULL,用户可以根据该指针的值判断分配空间是否成功。
要访问用new所开辟的结构体空间,无法直接通过变量名进行,只能通过指针p进行访问。
—END—