第一章 快速入门
1.while (cin >> str),为何 cin >> str 可以作为判断条件呢?
cin是istream类型的一个全局对象,
istream重载了隐式转换符,使得cin可以转换成bool类型,如下所示
operator bool() const
{return (_Ok); }
其中_Ok的值就会在每次输入的时候进行更改,如果遇到EOF或则输入无效,_Ok就会变为false,从而停止输入
第二章 变量和基本类型
1.初始化和赋值的区别?
初始化是指创建变量并给它赋值,而赋值则是擦除对象的当前值并用新的值代替,例如
A a;
A b = a;//调用的是复制构造函数
b = a;//调用的是赋值构造函数
2.变量的声明和定义的区别?
定义是给要变量分配空间,声明只是向程序表明变量的类型和名字
一般情况下,定义也包含了声明,但是可以利用extern关键字进行只声明不定义
3.cosnt的用法
- 定义在变量和参数、返回值前,表示常量
- 定义在指针上,根据const和*的位置,表面是指向常量的指针或者常量指针
- 定义在引用上,可以接受不同类型的引用(非const引用不行)
- 定义在函数体上,表示该函数不能更改类属性
- 定义在全局变量上,是该全局变量的链接属性变成了非extern,即外部文件无法访问(非const默认是extern)
4.#define和typedef的区别
#define只是简单的进行了文本替换,而typedef则是为类型取了个"别名"
这种情况区别比较明显:
#define pointer char*
pointer a,b;
相当于char *a,b; //a是指针,b是char
typedef char* pointer
pointer a,b; //a,b都是指针.
第三章 标准库类型(string,vector,bitset,分别代表“字符”,“各种类型”,“位”的容器)
1.在控制台中输入string类型时,忽略所有空白字符,同样,遇到空白字符会终止输入
2.string::size_type类型表示字符串的长度,即unsigned int类型,是一种防止溢出的方法,这种方法也应用于容器上,如vector<int>::size_type
3.容器vetcor不是一种类型,而只是一个类模板,
对于
类模板
,必须要把所泛类型指明后才算是一种类型,如vector<int>
4.vector操作对于迭代器的影响是什么?
任何改变vector长度的操作都会是迭代器失效,比如说添加操作,因为可能会空间不足,导致所有数据都迁移,这样作为一个指针的迭代器指向的位置已经无效,
并不是所有改变vector长度操作都会导致变动,但是为了统一,就会置为无效
5.bitset容器有啥功能?
bitset用来存放位数据,封装了许多对于位的操作,比如对一个二进制位的某个位置置1,统计一个二进制中1的个数,等等
第四章 数组和指针
1.如何对待string和c风格字符串
要尽量使用sting来操作字符串,而不是c风格字符串,因为方便和安全(前者提供空间的自动管理)
string可以调用c_str()来返回c风格字符串,
其返回类型是const char *
2.如何用typedef简化指向多维数组的指针
int a[][4] = {……};
typedef int int_array[4];
int_array *p = a;
第五章 表达式
1.delete与null
- 指向null的指针也可以进行delete
- delete一个指针后也最好将其设为null
2.常见的强制类型转换符
- static_cast:基本类型的强制转换(区别与c的强制转换,这里会做安全型检查,double*不能转换成int*)
- dynamic_cast:运行时子类和父类直接的指针或引用转换
- reinterpret_cast:指针指向类换型的强制转
- const_cast:去const操作,一般用于指针
实例:
#include <iostream>
using namespace std;
class CCTest {
public:
void setNumber( int );
void printNumber() const;
private:
int number;
};
void CCTest::setNumber( int num ) { number = num; }
void CCTest::printNumber() const {
cout << "\nBefore: " << number;
const_cast < CCTest * > ( this )-> number--;
cout << "\nAfter: " << number;
}
int main() {
CCTest X;
X.setNumber( 8 );
X.printNumber();
return 0;
}
using namespace std;
class CCTest {
public:
void setNumber( int );
void printNumber() const;
private:
int number;
};
void CCTest::setNumber( int num ) { number = num; }
void CCTest::printNumber() const {
cout << "\nBefore: " << number;
const_cast < CCTest * > ( this )-> number--;
cout << "\nAfter: " << number;
}
int main() {
CCTest X;
X.setNumber( 8 );
X.printNumber();
return 0;
}
输出:
8
7
第六章 语句
1.异常
在C++中,异常使用的不是很多,一些标准库也没用抛出异常,所以需要用户自己定义异常,异常抛出后可以不进行catch,这样程序会跳转到名为terminate的函数中,一般就会导致程序正常退出
在java中,许多标准库,抛出了异常,当调用这些接口时,必须进行catch或者抛向上一层,java的异常具有层次结构,能够还原异常发生时整个函数调用过程
第七章 函数
1.利用const关键字进行函数重载
只有在参数为引用或者指向const的指针针(const int *)时,在参数前面加上const才能进行重载
如果参数为非引用或者const指针,则无法重载
例如:
void f(const int i);
void f(int i);
void f(int cosnt * i)
void f(int *i)
这两对都是同一函数
2.如何利用函数改变一个指针的指向
- 把被调用函数的参数声明为指针的指针,实参传递该指针的地址
- 把被调用函数声明为指针的引用,实参传递该指针
例如:
void ptrSwap(int *&p1, int *&p2){
int *temp = p1;
p1 = p2;
p2 = temp;
}
3.声明形参为数组的方法
- void f(int * a);
- void f(int a[]);
- void f(int a[10]);
- void f(int (&a)[10]);
4.默认形参
对于一个函数,如果其中一个形参有默认值,那么这个参数后面的所有参数都应该有默认值
在声明和定义中,只能为一个形参指定默认实参一次
例如:
如果声明了void f(int a = 0),在定义中就不能再次指定默认数:int f(int a = 0){……}
对于含默认形参的重载,要防止重载出现不确定性
例如:
void f(int a, int c = 1){
cout << a << endl;
}
void f(int a){
cout << a << endl;
}
5.重载中的注意事项
正如上面几个例子,最重要的是要保证重载的清晰性
确定重载函数的几个步骤:
- 根据函数名,确定候选函数(局部函数名会覆盖全局函数名)
- 根据形参的个数确定第一批候选函数
- 根据形参的类型确定最终函数
按如下等级(即先后顺序)确定类型:
- 精确匹配
- 通过类型提升进行匹配
- 通过标准转换进行匹配
- 通过类类型进行匹配
这里要注意的是“类型提升”与“标准转换”,如下所示:
void f(int);
void f(short);
f('a')//将调用f(int)
char类型变成int类型,叫做字符提升;char类型变成short类型,叫做字符转换。前者优于后者
第八章 标准IO库
C++IO类型分为三类:
- iostream:定义在控制窗口进行读写的类型,类型与java中的Scanner类似
- fstream:定义读写已命名文件的类型,类型与java中的FileInputStream和FileOutputStream类似
- sstream:定义读写内存中的string对象,类似于java中的StringReader和StringWriter类似
与java一样,每种流通过相应的read和write函数进行IO操作,另外,每种流对象还重载了<<或>>操作符,其功能类似于read和write,每个流对象还有一个条件状态,用来表示该流对象是否可用,或者碰到了哪种特定的错误
java无法控制读取指针,C/C++可以利用读取指针进行跨越式读取
java打开文件很简单,直接把文件名放入一个IO流中就可以,
C/C++增加了文件模式这一概念,对打开动作进行了细化,如“只读模式”的打开,“直接定位到文件尾”的打开,等等