YeeKal

cpp1

YeeKal
"#"

from c to c++

预处理

#include<iostream>
using namespace std;

c++标准输入输出头文件不带后缀.h。c++头文件都不再带有扩展名。

若包含stdio.h还是可以使用printf,scanf等函数。

提前声明using,或者在引用函数时使用前缀std::std::cout<<std::endl;

在main()函数中声明命名空间,则用户自定义函数不能使用该空间。

data type

bool: true/false;

字符函数库

#include<cctype>
isalpha();
isspace();
islower();
......

string

char dog[8] = { 'a','y','d',' ','o','k','h','h' };
char cat[8] = { 'a','y','u',' ','o','k','h','\0' };
cout << dog << endl;
cout << cat << endl;

dog[]is not a string; when printing this, it will continue outputing until encountering a '\0'.

char cat[]="cat";

string constant(字符串常量),自动在结尾加上空字符。

cout输出时,任何两个由空白(空格,制表,换行)分隔的字符串常量都将自动拼接,中间不加空格。

<cstring>处理字符串的标准库。

字符串输入

cin>>cat;//cin使用空白(空格,换行,制表)确定字符串的结束位。
cin.getline(name,20); //面向行的字符串输入
                      //读取到换行符并将换行符丢弃,或指定字符数(20-1)结束
cin.get(name,size);
cin.get(score,size);//a problem
                    //cin.get()可以有与getline相同的参数,读到换行或指定字符,
                    //但是会把换行符滞留在缓冲区,因此第二个get()将永远读取不到数据
cin.get(name,size);
cin.get();//不带任何参数可读取下一个字符,包括换行符
cin.get(score,size);//因此中间插入不带参数的get()解决换行符滞留

cin.get(name,size).get();//也可以解决换行符滞留,<*crazy*>

空行与失效位

字符串与数字混合输入

cin>>也会滞留换行,因此cin之后的输入会被阻塞,因此要丢弃缓冲区中的换行符。

cin>>year;
cin.get();
(cin>>year).get();//这是一个神奇而有效的方法,后面续接的.get()可以看成最后的清扫

string class

#include<string>
using namesapce std;
string str1;
string str2="pants";//字符串初始化string对象
                    //cin输入
                    //cout输出,数组表示访问字符
str1 +=str2;    //拼接
#include<cstring>
strcpy(str1,str2);//copy str2 to str1 
strcat(str1,str2);//append str2 to str1
int len1=str1.size();//str1是一个对象,size是方法,不能用strlen试图获取string对象的长度
int len2=strlen(charr1);//c-style
             //string在应付字符数组超空间方面有优势
//string行输入
getlinecin,str1;
cout<<R"(Jim "king" i)"<<endl;
//原生字符串,以避免符号转义的过度复杂

struct

c++允许在声明变量时省略struct

定义时是分号,初始化是逗号;

student stu {"yee",345,0.9};//列表初始化

共用体union

枚举enum

指针

int * ptr;//*两边空格可选
int* ptr1,ptr2;//ptr1是指针,而ptr2是整形变量,要对每一个变量使用*

new分配内存

int *ptr=new int;
*ptr=23;
delete ptr;//释放内存,而不是删除ptr本身
delete ptr;//不能释放已释放的内存块
            //compared to c: malloc()/free()
int *ptr1=new int;
int *ptr2=ptr1;
delete ptr2;//ok,delete的关键是释放由new所分配的内存
cin>>len;
int *ptr=new int[len];
delete []ptr;//the style is cute

指针与数组

数组是常量,指针是变量

int tell[10];//数组地址
cout<<tell<<endl;//display &tell[0]
cout<<&tell<<endl;//display adress of whole array
        //对数组取地址,数组名不会被单纯地解释为地址,与指针不同
        //数值上看两者结果一样
        //概念上(tell+1)地址加1,而(&tell+1)地址加10

指针与字符串

给cout一个指针,它将打印指针指向的地址。如果指针是char *,cout将打印整个字符串。因此要强制转换为另一种指针类型(int *)ptr来显示指针所指向的字符串的地址。

char *ps;
char animal[]="fox";
ps=animal;//这样做只是把地址赋值给ps

//深度复制
ps=new char[strlen(animal)+1];//分配足够的内存空间
strcpy(ps,animal);

语句结构

循环

do
{}
while();

逻辑操作符

&&,||优先级低于算术操作符,而!高于关系和算术操作符,因此取反时要用括号将表达式括起来。and操作符高于or.

条件操作符

exp1 ? exp2:exp3;

int c= a>b ? a:b;//取最大值

文件读写

#include<fstream>
using namespace std;
ofstream outfile;  //
outFile.open("edit.txt");
cout << "write to file:" << endl;
outFile << "year:" << year << endl;
outFile << "name:" << s << endl;
cout << "done\n";
outFile.close();//与cout一致

//方法
outfile.precision(2);//设置精确度
//read

函数

使用数组区间

int sum(const int *start,const int *end){
  int * pt;  
  for(pt=start;pt<end;pt++)
  {}
}

函数名既是函数地址。

double pam(int);//this is a function
double (*pf)(int);//a pointer to a function
pf==pam;
(*pf)(5);//函数调用
double *pf(int);//括号优先级较高,本语句是生命了一个返回指针的函数,注意区别

内联函数

固定一块内存,执行函数。若为执行改函数而做的前期准备工作比较耗时,则内联函数以占用内存为代价节省一部分时间。多习惯把内联函数的定义也放在函数声明处。

内联函数不能递归。

c++新增特性。c中的宏定义是内联的原始形式。

inline double square(double x);//原型和定义都要使用关键字inline

引用变量

引用变量旨在创建一个别名的副本,与原变量有相同的值和地址。

int rats=20dogs=30;
int &rodents=rats;//引用变量,必须在定义时初始化。
rodents=dogs;   //引用一旦创建,不可再改变为其他的引用,
                //因为任何的重新改变引用对象的操作实际上都是赋值操作
//rodents和rats都变成20,并且地址相同,而与dogs地址不同

因此引用变量的实质是给相同的地址取一个别名。这经常被用在函数参数上以改变变量的值,而不必借用于指针。将引用作为函数参数实质是按值传递,不需要另外定义引用变量。

void square(int &a);//引用,相同地址,传递地址
void squera(int a);//传递值

对于任何具有更改值的参数都可以使用const限定词保护数值不变。

结构作为参数使用引用。

默认参数

char * left(const char *str,int n=1);
left("thesift",3);//调用时n=3覆盖原来的默认值
left("thesift");//调用时n默认设置为1

默认参数必须放在参数列表的右边。若有多个默认参数,则实参按照从左到右的顺序依次赋给对应的值,中间不可以跳过不赋值。默认参数在函数原型里面声明即可。

int hargo(int n,int m=1,int p=2);
hargo(2);//valid
hargo(2,3);//valid
hargo(2, ,3);//invalid

函数重载

同一个函数名不同的功能。函数重载的关键是函数的参数列表,即函数特征标识(function signature),即参数的数目和类型。c++允许函数名相同而特征标识不同的函数。

即便是强制类型转换后不与任何标识匹配,或与多个标识匹配的函数调用将被视为错误。

有些特征表是不能共存的:引用,const

double cube(double x);
double cube(double &x);//invalid

void drib(char *bits);
void drib(const char *bits);//valid

特征标识不包括函数类型。重载函数的返回类型可以不同,但与此同时特征标识也必须不同。(本就如此嘛)

函数执行相同的任务,而参数类型不一样时多食用重载。

函数模板

template <typename AnyType>
void swap(AnyType &a, AnyType &b)
int main(void){
  return 0;
}
template <typename AnyType>         //声明建立模板,类型名自定义,如T;typename可以换                                  //成class,旧式写法
                                //函数原型和函数定义都需要模板声明
void swap(AnyType &a, AnyType &b) {
    AnyType c;
    c = a;
    a = b;
    b = c;
}//调用函数时可以用int,float,string等

模板不创建函数,当需要交换数据时,编译器再按模板模式创建这样的函数实例(specialization)。

重载模板

//重载模板,也需要标识不同
template <typename T>
void Swap(T &a,T &b);
template <typename T>
void Swap(T *a,T,*b,int n);
//第二个模板函数的第三个参数没有使用泛型

模板有其局限性,并不是所有的数据类型都有某一种相似的操作。

显式具体化

多用于结构,类的特殊操作。

void Swap(job &,job &);//非模板函数

template <typename T>//模板函数
void Swap(T &,T &);

template <> void Swap<job>(job &,job &);//显式具体化模板函数
template <> void Swap(job &,job &);//即可以去掉<job>
/*
优先级:非模板函数>显式具体化>模板函数
*/

显式实例化

未深究

template <typename T>
T Add(T a,T b);

int m=6;
double x=10.2;
Add<double>(x,m);//将强制把m转换为double
                //<double>声明了专门的类型

内存管理

静态变量

int global://static ,external
static int flit;//static internal
int main(){
    for(;;){
        static int t=0;//static,no linkage
    }
}

未初始化的静态变量所有位被设置为0

外部静态变量

单定义(one definition);

所有的引用都需要声明;

两种声明方式:定义声明(definition declaration),即初始时的定义;引用声明(referencing declaration),即外部声明。

extern int cats;//外部声明必须使用extern关键字
extern int dogs=20;//定义时可以省略extern

内部静态变量

同名将覆盖其他文件中的外部静态变量。外部变量实现不同文件间的数据共享,内部静态实现同一文件内不同函数的数据共享。

说明符和限定符

存储说明符(storage class specifer)

  • auto
  • register
  • static
  • extern
  • thread local
  • mutable

cv-限定符(cv-qualifier)

  • const
  • volatile

在c++(not in c) const对全局变量的作用使其链接性变为内部。因此倘若在头文件中定义了一个全局常量const int t=8则有多个源文件包含头文件时并没有违反“单定义”规则。

函数链接性

c++不允许在函数内部定义函数。与变量一样,函数默认为静态,具有外部链接,即可以在文件间共享函数。当然可以在函数原型中使用extern表示函数在另一个文件中定义,但一般不需要这样做。可以使用static定义内部函数拒绝外部文件访问该函数。

动态分配

int *ptr=new int[10];
delete(ptr);
//初始化
int *pd=new int (6);
int *ar=new int[4] {2,4,6,7};//对于数组或结构需要使用大括号,当然大括号也可用于单值
int *ptr=new int;
int *pd=new int [10];
//equal to
int *ptr=new(sizeof(int));
int *pd=new(sizeof(int)*10);

定位运算符

定制内存块

名称空间