(一)概述
C++:在原有C的基础上(保持了C语言的功能强目标代码效率高和可移植性好等优点)扩充了支持OOP(面向对象设计,实现了软件重用。),还有出色的错误检查机制,他提供了专门的机制检查类,更合适大,中型程序的开发。
示例:
//这个是一个C++程序
#include<iostream>
#include<cstdlib>
using namespace std;
void main()
{
cout<<"Hello C++!\n";
int a;
cin>>a;
//输入非数字,会出现不可预知的数
cout<<a;
system("pause");
}
(二)C++程序基本要素
标识符:程序员或者系统定义的符号,用来标识变量,类型和函数等(用来命名函数,变量,自定义类型/系统保留字)。命名规范:字母/下划线开头。
关键字:C++编译预定义的,具有固定意义的保留字。
变量与常量
运算符和表达式
操作符的优先级和结合性图表:
优先级 操作符
1 ::
2 . -> [] ()
3 ++ -- ~ ! - + & * sizeof new delete castname_cast<type> :
4 .* ->*
5 * / %
6 + -
7 << >>
8 < <= > >=
9 == !=
10 &
11 ^
12 |
13 &&
14 ||
15 ?:
16 = *= /= %= += -= <<== >>== &= |= ^=
17 throw
18 ,
结合性:除非了3,,16都是向左结合,其他都是向右结合。</span>
(三)数据类型
(1)整型:在内存是以二进制补码表示,另外有符号的首位为符号位(这里不阐述)。
C++标准:char<=short int <= int <= long int
附录:32位编译器整数类型一览表:
数据类型 字节数 位数 表示范围
char 1 8 -2^7~(2^7-1)
int 4 32 -2^31~(2^31-1)
long 4 32 -2^31~(2^31-1)
short 2 16 -2^15~(2^15-1)
signed char 1 8 -2^7~(2^7-1)
(2)整数子类:字符型,枚举型,布尔型。
字符型:是针对处理ASCII字符而设计的,可以用signed char的正数表示ASCII的码值。
示例:
//取字符的ASCII的码值
#include <iostream>
#include<cstdlib>
using namespace std;
void AsciiValue(){
//67对应C
char a = 67;
char c = a+1;
//68对应D
cout<<c;
system("pause");
}
枚举型:enum 名字{.......};
布尔型:true/false
(3)浮点型:
float:32位,4字节
double:64位,8字节
(4)C-串与string
C-串:过时了,使用string类型
在内存的存储方式:
'H' | 'e' | 'l' | 'l' | 'o' | '!' | 0 |
C-串是char*,字符指针指向第一个元素
示例:
//字符指针
#include <iostream>
#include<cstdlib>
using namespace std;
void charPointer()
{
char* str1 = "hello";
//字符指针指向第一个元素,输出h
cout<<str1<<endl;
char a = 'a';
//字符为1字节,字符指针为4字节
cout<<sizeof(a)<<endl<<sizeof(str1)<<endl;
//输出长度为5,指的是字符个数。
cout<<strlen(str1)<<endl;
system("pause");
}
string:
string常见方法:
示例:
//================================================================================
//stringfuction.cpp
//常见string函数示例
//================================================================================
#include <iostream>
//algorithm意为"演算法",是C++的标准模版库(STL)中最重要的头文件之一,提供了大量基于迭代器的非成员模版函数。
#include <algorithm>
#include<string>
using namespace std;
void stringfuction(){
string a;
string s1 = "hello";
string s2 ="123"; //作用 输出
a = s1; //复制
cout<<(a==s1?"":"not")<<"equal\n"; //比较 equal
cout<<a+s2<<endl; //连接 hello123
reverse(a.begin(),a.end()); //倒置
cout<<a<<endl; // olleh
//表示从第0个开始到第4个结束,取前4个字符,改变为c,replace有多种重载函数。
cout<<a.replace(0,4,4,'c')<<endl; //替代串 cccch
cout<<(s1.find("ell") != -1?"":"not")<<"found\n";//查找串
cout<<(s1.find('e') != -1?"":"not")<<"found\n"; //查找字符
string流操作:
引用sstream,fstreanm操作文件流(读取文件中,结果为string数组line)和string流(读取line string中的元素 以空格结束)。
示例:
<pre name="code" class="cpp">//=======================================
//从txt中读取行的数据,累加行数据。
//=======================================
#include <iostream>
#include<fstream>
#include<sstream>
using namespace std;
//---------------------------------------
void StringSum(){
//ifstream 表示 in file stream 输入文件流
//ifstream 文件流名称(文件);
//ofstream 相同
//很多输出输入流的值都是true/false,所以可以用来判断,比如放在for循环判断语句或者if判断语句。如cin,getline,cin.get()读入字符
//绝对路径和相对路径未解决,这里txt文件放在和cpp文件同一个目录下。
ifstream in("aaa.txt");
//上面表示声明一个输入流in,文件应该和cpp一个目录
//如果为读入失败那么for循环结束,for循环第3个表示什么都不做。
for(string s;getline(in,s);){
int a;
int sum=0;
//声明输入string流,引用了sstream,作用是挨个读取整数,返回值为true/false,false的时候停止执行。
istringstream sin(s);
//for(;sin>>a;){
// sum += a;
//}
//for循环可以替代while循环,1可以放在外面,2判断放while里面,3循环执行后可以放在while循环语句最后。
while(sin>>a){
sum += a;
}
cout<<sum<<endl;
}
}
(5)数组
声明与初始化:
//声明
int a[n]; //错误,必须为常量
int a[5]; //正确
int a0['a']; //正确,a为char,char是整型的子集,对应的ASCII为97 表示为a0[97]
//初始化
int a1[5] ={1,2,3,4,5,6}; //错误:初始值个数大于下标数
int a2[5] ={1,,2,3,4,}; //错误,空值不能以逗号方式省略
int a3[5] ={1,2,3,}; //同上
int a4[5] ={}; //错误,初始值不能为空
int a5[5]={1,2,3}; //正确,后面的元素为0
int a6[5]={0}; //正确,全部为0
//字符数组的特殊性:
char ch1[6]={"hello"};
char ch2[5]={'h','e','l','l','o'};
char ch3[6]="hello";
//1,3的字符数为6,能用来做C-串操作,2不能,这么设计是为了满足编程的方便,不过对于C-串这种落伍的还是不接触为好。
默认值:
示例:
//================================================================================
//AttaysTest.h
//数组默认值测试
//================================================================================
#include <iostream>
using namespace std;
//--------------------------------------------------------------------------------
int a1[5]={1,2,3}; //函数外部有初始化
int a2[5]; //函数外部无初始化
//--------------------------------------------------------------------------------
void AttaysTest(){
int a3[5]={2}; //有初始化
int a4[5]; //无初始化
cout<<"a1:";
for(int i=0;i<5;i++){
cout<<a1[i]<<" ";
}
cout<<"a2:";
for(int i=0;i<5;i++){
cout<<a2[i]<<" ";
}
cout<<"a3:";
for(int i=0;i<5;i++){
cout<<a3[i]<<" ";
}
cout<<"a4:";
for(int i=0;i<5;i++){
cout<<a4[i]<<" ";
}
}
/*输出结果:
a1: 1 2 3 0 0
a2: 0 0 0 0 0
a3: 2 0 0 0 0
a4 -858993460 -858993460 -858993460 -858993460
分析:全局数组未初始化则默认值为0
局部数据未初始化,debug模式下会被VC赋值为0xcccccccc也就是-858993460
只初始化1个或者几个数,那么缺省的默认为0
*/
二维数组:
示例:
//================================================================================
// Test2DArrays.h
//二维数组测试
//================================================================================
#include<iostream>
using namespace std;
//--------------------------------------------------------------------------------
void Test2DArrays()
{
//初始化的默认值规则和一维数组的一致
//这是2种初始化的方式
int a1[2][3] = {1,2,3,4,5,6};
int a2[2][3] ={{1,1,1},{2,2,2}};
cout<<"a1:";
for(int i=0;i<2;i++)
for(int j=0;j<3;j++)
cout<<a1[i][j]<<" ";
cout<<"\n"<<"a2:";
for(int i=0;i<2;i++)
for(int j=0;j<3;j++)
cout<<a2[i][j]<<" ";
cout<<"\n";
}
//=================================================================================
(6)向量
(7)指针与引用
示例:指针的初始化和间接访问
//=================================================================================
//TestPoniters.h
//指针的初始化和间接访问
//=================================================================================
#include <iostream>
using namespace std;
void TestPoniters(){
<span style="white-space:pre"> </span>int count = 18;
<span style="white-space:pre"> </span>int* p1; //声明一级指针
<span style="white-space:pre"> </span>p1 = &count; //&取址运算符。初始化,指针p1的值为count的地址
/*<span style="white-space:pre"> </span>p1 = &18; */ //错误,字面值不认为是具有空间地址的实体。
<span style="white-space:pre"> </span>cout<<p1<<" "<<*p1<<endl;
<span style="white-space:pre"> </span>int** p2;
<span style="white-space:pre"> </span>p2 = &p1;
<span style="white-space:pre"> </span>cout<<&p2<<","<<p2<<" "<<*p2<<" "<<**p2<<""<<endl;
<span style="white-space:pre"> </span>cout<<sizeof(p2)<<","<<sizeof(*p2)<<","<<sizeof(**p2)<<endl; //4字节
}
//=================================================================================
//32位机 内存的存储单元为字节 相邻地址差12字节,16进制为C
/*VC在Debug状态下,会给每个栈变量的前后都插入4个字节的保护值:0xcccc。这样,本身4字节,加上前后各4字节的保护值,一共占有12个字节。
保护值的目的是让VC系统在Debug状态下,分析你的赋值语句是否越界。
如果在VC的Release下运行,则差为4。
输出:
0012FE8C 18
十进制(1244812)
分析: count的地址,值。p1指向count的地址,*p1通过count的地址间接访问count的值。*
表示间接访问。
0012FE74 0012FE80 0012FE8C 18
十进制: 1244788 1244800 1244812
p2的地址 p2的指向地址 p2指向地址的值 (p2指向地址的值)的值
取址运算 p2的值 p1的值 count的值
&p p2 *p2 **p2
访问p2的地址 访问p2 间接访问p1的值 (间接)间接访问count的值
*/
指针类型:
指针是有类型的:int* p1; double *p2....
而内存空间中的实体都是没有类型的,为二进制位码。如果int类型变量代表一个32位空间实体,那么这个空间在被访问的时候就理解为整数实体。
示例:空间实体的理解和强制转换
//==============================================================================
//PointerTypeAndCast.h
//空间实体的理解和内存数据重解释类型
//==============================================================================
#include <iostream>
using namespace std;
void PointerTypeAndCast(){
double b = 11.2;
double* b1 = &b;
int* a = reinterpret_cast<int*>(&b);
cout<<*b1<<" "<<*a<<"\n";
}
//==============================================================================
/*
输出: 11.2 171798918
分析:reinterpret_cast为重解释类型。因为空间实体在内存的表示方式为二进制位,那么
强制用int类型的解释方式来解释b的内存值。
存在必有需要的理由,不过这样过于放肆。算是一种叛逆的设计,重解释转换。
*/
指针运算
示例:数值指针运算
//=============================================================================
//PointerOperations.h
//数组指针运算示例
//=============================================================================
#include <iostream>
using namespace std;
void PointerOperations(){
<span style="white-space: pre;"> </span>int a[5]={1,2,3,4,5};
<span style="white-space: pre;"> </span>for(int* ip=a;ip<a+5;ip++)
<span style="white-space: pre;"> </span>cout<<ip<<","<<*ip<<endl;
}
/*
输出:0012FE7C,1
0012FE80,2
<span style="white-space: pre;"> </span> 0012FE84,3
<span style="white-space: pre;"> </span> 0012FE88,4
<span style="white-space: pre;"> </span> 0012FE8C,5
分析:int类型占4字节,内存存储单位为1字节,所以内存差为4
如果是对folat,double操作也是4,对char为1,与该类型的字节大小有关。
a表示为数组a首个元素的地址,如果要写成&a[0]也可以。
指针增减应该在数组的表示范围内,不然是危险的,会访问别的数据。
*/
指针限定
可以把内存地址和值看成一键值对,address/value
常量指针:指向常量的指针,值不可以改变,value不改变
指针常量:指针的变量值不可以改变,address不可以改变
双重修饰,常量指针常量,address/value都不可以改变。
示例:
const int a = 5;
int b = 10;
int c = 18;
const int*p1 = &a; //const修饰指向的实体类型---常量指针
*p1 = 87; //错,指向的实体类型是常量,不可改变
ip = &c; //正确,可以修改指针值
int* const p2 = &b; //const修饰指针变量---指针常量
*p2 = 18; //正确,指针常量可以修改指向的实体
p2 = &c; //错误,指针常量的指针值是常量
int const*p3 = &c; //同上
const int* const p4 = &c; //双重修饰,常量指针常量,address和value均不可以修改
引用:
C#中用关键字ref,在C++中用&
示例:int a=5; int&b= a;
示例:引用及其地址
//=============================================================================
//TestRef.h
//引用测试
//=============================================================================
#include <iostream>
using namespace std;
void TestRef(){
int a = 5;
int& b = a;
cout<<b<<","<<&b<<endl;
cout<<a<<","<<&a<<endl;
b = 10;
cout<<b<<","<<&b<<endl;
cout<<a<<","<<&a<<endl;
}
//=============================================================================
/*输出
5,0012FE8C
5,0012FE8C
10,0012FE8C
10,0012FE8C
分析:引用只能引用一个实体,而指针可以改变指向的实体。对引用进行操作也就是对实体进行
操作。
*/
日期:2014-10-4 至 2014-10-5