C++ 备忘录

1
#include <iostream> //切记不是iostream.h哦

using namespace std; //命名空间,最好加上 名字空间:就是C++标准库所使用的所有标识符(即类,函数,对象等 的名称)都是在同一个特殊的名字空间(std)中来定义的 如果没有这条指令,我们将需要使用 std::cout 这样的语法 来调用输出流对象

cout 输出流

重载:就是允许我们按照不同的方式使用同一个操作符

cin 对象类型为istream,从用户终端如何读取数据

cin >>i;// cin输入操作符又称为提取操作符,它一次从输入流对象cin提取一个整数

当用户点击键盘上的‘Enter’键时,操作系统把键盘缓冲区的内容 传输到cin流的内部缓冲区,“>>”操作符随后从这个缓冲区提取需要的信息

/cin流内部缓冲区就是stdin/

>>’可以从输入流对像提取出int,floatdouble型数据,也可以提取字符串等数据 cin>>i 返回输入流对象本身,也就是cin,但是如果到达文件尾或者提取操作符遇到一个非法值,这个返回值将是False

C & C++区别: C++允许程序在程序的任意位置声明变

cin、cout对象的多个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
-cin.ignore() 忽略()个不读,一般用于清空键盘缓存区
-cin.getline() 两个参数
-cin.peek()
-cin.get()
-cin.read() //读取
-cin.gcount() //计算缓冲区中的字符个数
-cin,sync() 用来清除键盘缓冲区中未读取的内容
-cout.write() //从缓冲区中输出()个字符
-cout.precision() 确定输出结果的有效位数 ,0时候默认为6位有效数字
-cout.width() 数据长度不足则左补空格,设置输出宽度
cout << buf <<endl;//endl 回车加清空缓冲区

在C++里用 const int SIZE = 50;//例子
来定义全局变量

main()函数的参数
argc 整型变量(命令行命令个数)
argv[] 字符指针数组
argv[]的每个指针指向命令行的一个字符串

$getc()的返回值是int类型

C++文件操作

1
2
3
4
#include <fstream> //文件操作的头文件(文件读取类)
ifstream in
ofstream(文件写入类)
ofstream out //感觉和文件关联差不多

常见的打开模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ios::in--打开一个可读取文件
ios::out--打开一个可写入文件
ios::binary--以二进制的形式打开一个文件
ios::app--写入的所有数据将追加到文件的末尾
ios::trunk--删除文件原来已存在的内容
ios::nocreat--如果打开文件并不存在,那么以此参数调用open函数将无法进行
ios::noreplace--如果要打开的文件已存在,试图用open函数打开时将返回一个错误
Ps:可以用 或 操作来实现多种打开模式并存(其实打开模式就是枚举类型)
ios::beg--使得文件指针指向文件头
ios::end--使得文件指针指向文件尾
ifstream out
out.seekg //文件定位
///////cin & cout 可以自动对不同类型的字符进行匹配
For Example:
double a;
char b
cin >> a >>b;//自动匹配哦,但必须以空格间隔开哦~~~~~~~~~~~~~~~~~~

cin 对象有几个专门用来报告其工作情况的成员函数,它们将返回一个真/假 值来表明cin 的状态

1
2
3
4
-eof();如果文件到达文件(或输入)末尾,返回true
-fail():如果cin无法工作,返回true
-bad():如果cin因为比较严重的原因(如内存不足)而无法工作,返回true
-good();如果以上情况都没发生,返回true

const变量默认是extern , 要使const 的变量能够在其他文件中被访问 , 必须显示的声明为extern

1
2
3
4
5
6
E.G
//file.cc
extern const int bufSize = function();
//file2.cc
extern const int bufSize;//uses bufSize from file.cc
//do what you want to do

以下的内容是合法的

1
2
3
int i = 42;
const int &r = 42;//legal for references only
const int &r2 = r + i;

1
2
3
4
5
double dval = 3.14;
const int &ri = dval;
编译器会将其解释为:
int temp = dval;//create temporary int from the double
const int &ri = temp;

显然这个程序为了改变dval 的值的类型 , 但是这样做却事与愿违 , dval并未变。 仅允许const引用绑定到需要临时使用的值完全避免了这个问题 , 因为const是只读的

const引用只能绑定到与该引用同类型的对象
const引用则可以绑定到不同但相关的类型的对象或绑定到右值

typedef的使用目的

1.为了隐藏特定类型的实现 , 强调使用类型的目的
2.简化复杂的类型定义 , 使其容易理解
3.允许一种类型用于多个目的 , 同时使得每次使用该类型的目的明确

枚举
定义和初始化枚举

1
2
3
4
5
//input is 0 , output is 1 , and append is 2
enum open_modes
{
input , output , append
};

枚举定义包括关键字enum ,其后是一个可选的枚举类型名
默认的, 第一个枚举成员赋值为0 , 后面的每个枚举成员值比前面的大1
使用方法:

1
2
3
4
5
6
7
8
9
enum Points
{
point2d = 2 , point2w,
point3d = 3, point3w
};
Points pt3d = point3d;
Points pt2w = 3; //error:pt2w initialized with int
pt2w = polygon; //error;polygon is not a Points enumerator
pt2w = pt3d; //ok

C++中 , 可以使用classstruct 来定义一个类 唯一区别是:影响默认的初始访问控制 class:private struct :public

头文件一般包含类的定义、extern变量的声明和函数的声明

编译、连接的两种方式:
1、将源文件逐一编译 , 按顺序~~编译连接
2.将各个文件分别编译后将目标文件相连接

头文件用于声明而非定义

1
2
extern int ival = 10;
double fica_rate;

虽然ival声明为extern, 但是有初始化式,为定义 fica_rate的声明虽然没有初始化式, 但没有关键字extern , 也是一个定义

同一个程序中有两个以上的文件含有上述任意定义都会导致多重定义连接错误

对于头文件不该含有定义这一规则有三个例外:
头文件中可以定义类 , 值在编译时就已经知道的const对象和inline函数
原因:为了产生能定义或使用类的对象的代码, 编译器需要知道组成该类的数据成员,同样还需要知道能够在这些对象上执行的操作。 类定义提供所需要的信息。

变量的定义默认为extern,要想使常量(const变量)能够在其他文件中访问,必须在定义时显示指定它为extern

如果const 变量不是用常量表达式初始化的, 那么它就不应该在头文件中定义,相反,和其他变量一样,const变量应该在一个源文件中定义并初始化。应在 头文件中添加extern声明,以便其能被多个文件共享(将这个非常量表达式初始化的const变量定义在源文件中, 但是要想使多个文件共享, 那么必须在头文件中声明为extern

可以使用下面的措施来预防多次包含同一头文件

1
2
3
4
#ifndef SALESITEM_H
#define SALESITEM_H
//
#endif

当没有两个头文件定义和使用同名的预处理器变量时, 这个策略相当有效。 我们可以用定义在头文件里的实体(如类)来命名预处理器变量来避免预处理器的变量重名问题。一个 程序中只能包含有一个名为Same_item类。通过使用类名来组成头文件和预处理器变量的名字,可以使得 很可能只有一个文件将会使用该预处理器变量

经典题型:
列出几种定义vector 对象的方法, 给定10个元素 , 每个元素的值为42.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//method1:
vector<int> ivec(10 , 42);
//method2:
vector<int> ivec(10);
for(vector<int>::size_type index =0 ; index < ivec.size() ; index++ )
{
ivec[index] = 42;
}
//method3
vector<int> ivec(10);
for(vector<int>::iterator iter ivec.begin() ; iter != ivec.end() ; iter++)
{
*iter = 42;
}
//method4
vector<int> ivec;
for(cnt i =0 ; i <10 ; i++)
{
ivec.push_back(42);
}
//method5
vector<int> ivec;
vector<int>::iterator iter = ivec.end();
for(int i =0 ; i != 10 ; ++i)
{
ivec.insert(iter , 42);
iter = ivec.end();
}

综上, 后两种方法比较灵活,比较好

关于vector和指针数组的一个例子!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//很重要的一个应用!!!
#include <iostream>
#include <string>
#include <vector>
#include <cstring>
using namespace std;
int main()
{
vector<string> svec ;
string str;
cout<<"enter string "<<endl;
while(cin>>str)
{
svec.push_back(str);
}
char **parr = new char*[svec.size()]; // 为你接下来的分配的指针提供容器《分配指针数组!》
size_t ix = 0;//使用的数据类型要严谨
for(vector<string>::iterator iter = svec.begin();
iter != svec.end() ; iter++ , ix++)
{
char *p = new char[(*iter).size()+1];
strcpy(p , (*iter).c_str());
parr[ix] = p;
}
for(ix = 0 ; ix != svec.size() ; ix++)
{
delete []parr[ix];
}
return 0;
}

左值: 左值可以出现在赋值语句中的左边或右边
右值:右值只能出现在赋值语句的右边 , 只可以对其结果进行读取,而不可以对其进行赋值

1
*iter++ <=> *(iter++)

swich-case 语句常见错误:

1.语句后忘加break , 如果有特定需要,则需要在程序中注明
2.不要在中间case语句中声明并初始化变量, 防止使用未定义的变量 , 当然 , 要使用的时候使用复合语句
3。case语句后面只能跟一个值!
4.case语句后必须跟一个 const!1!

在调试时很有用的预处理器常量
__FILE__程序所在的文件名
__LINE__出错的行数
__DATE__出错的日期
__TIME__出错的时间

常用流

1
2
3
4
5
6
istream
iostream
ostream
fstream
ifstream
ofstream

析构函数不能对指针成员进行释放,必须使用delete

使用值型类时, 必须定义复制构造,重载=运算符 ,定义析构函数

虚函数的动态绑定只适用于指针或引用,如果是类对象调用该虚函数,则不会自动绑定滴

一个类中只要有纯虚函数(无论显示或隐式),该类就是抽象类!

所谓隐式就是没有定义其对应基类的纯虚函数,而是直接给继承了!!

句柄类对象一旦调用某个函数,可以牵一发而动全身!!!
经典例子:

1
2
3
4
Query q = Query("hello ") & Query("wind") | Query("boy");
cou<<q;
q.eval();
//在上述的输出和调用中,有一个原则:必须结构等式的右边找出该式用过的所有类对象,并调用所有对应的函数啊!!!

赋值运算其实就是删除原有的元素,赋予最新的元素!!! 两步哦

句柄类一旦关联了对象以后,它的生死就掌握在句柄类的手中,而不可以由用户或者是程序的其他部分将他删除,否则会引起很蛋疼的运行错误的!!!

易错题:

1
2
3
4
5
6
7
8
9
namespace cplus
{
namespace Maxtri
{
class max
{};
max operator* (const max & , const max &);
}
}

定义方法

1
2
cplus::Maxtri::max cplue::Maxtri::operator*(const max& , const max&)
{}

接受类类型形参(或类类型指针及引用形参)的函数(包括重载操作符),以及与类本身 定义在同一命名空间的函数(包括重载运算符),在类类型对象(或类类型引用及指针) 作为实参的时候是可见的 可见的意思:就是使用时不需要加上作用域限定符
例如:

1
2
std:string s;
cin>>s;

1
string *s = new string("hello!");

new的工作原理:
1.调用名为 operator new的标准卡函数,分配足够大的原始的位类型化的内存,以保存指定的一个对象
2.接下来,运行该类型的一个析构函数,用于指定初始化构造对象
3.返回指向新分配并构造的对象的指针

1
delete s;

deletw的工作原理
1.对该指针指向的对象运行适当的析构函数
2.通过调用operator delete 的标准库函数释放该对象的内存

从delete工作可以看出: allocator要想彻底释放一个内存,必须首先使用指针指向的对象的析构函数将该对象析构: alloctordestroy() 然后再使用alloctordeallocate 成员对内存进行释放

调用析构函数的效果是适当滴清除对象本身。但是,并没有释放对象所占的内存!!!!
调用operator detete 函数不会运行析构函数,它只释放对象所占的内存

1
2
new (sp) string(b , e)
alloc.construct(sp+1 , string(b , e));

热评文章