【面试相关】【C++进阶】阅之丰:《程序员面试笔记—C/C++、算法、数据结构篇》(by_杨&吴&王)
[by_041]
C++程序设计基础(第10章)
#include < > / " "
的区别
#include < >
直接在编译器指定路径搜索,失败直接报错#include < >
先在当前目录搜索,失败后再从编译器指定路径搜索,再失败报错
#define #/##
的作用
- #可以把后面的宏参数作为完整字符串替换
- ##可以把其前后的宏参数进行字符串化的连接
#include<iostream>
using namespace std;
#define f(x) cout<<#x<<"\t:\t"<<x<<endl;
int main(int argc, char *argv[])
{
f(10);
f("abc");
f(1.3);
return 0;
}
/*输出:
12345 : 12345
"abc" : abc
1.234 : 1.234
*/
断言(ssert)的概念
assert(???);
:???中的表达式为真则无事发生;为假即检测失败,程序会向标准错误流stderr中输出错误信息,再调用abort函数终止程序执行(只在DEBUG过程中起作用,RELASE无效;如是说但在使用时要达到这个效果要在编译时加入以下命令-DNDEBUG
)
#define NDEBUG //禁用assert宏,记得在引用库上面
#include<assert.h> //包含assert库
assert(?); //调用assert函数
变量
- 修饰词
extern
:任何通过include包含该文件的文件中都可以使用这个全局变量static
:静态局部变量只在第一次申请时初始化赋值,之后执行到该语句无事发生,该变量的作用依旧停留在函数内部,但生存期会是整个程序的生命周期;静态全局变量,兼具静态变量(只一次初始化)和全局变量(作用于全局)的特性const
:修饰常量型变量,其值不能修改
(++i)+(++i)+(++i)
- 在VC中:先三次递增i,再求和,结果为 ( i 0 + 3 ) + ( i 0 + 3 ) + ( i 0 + 3 ) = 3 × ( i 0 + 3 ) (i_0+3)+(i_0+3)+(i_0+3)=3\times(i_0+3) (i0+3)+(i0+3)+(i0+3)=3×(i0+3)
- 在GCC编译器中:先进行前两次递增,求一次和后再递增第三次,最终求和,结果为 ( ( i 0 + 2 ) + ( i 0 + 2 ) ) + ( i 0 + 3 ) = 2 × ( i 0 + 2 ) + ( i 0 + 3 ) ((i_0+2)+(i_0+2))+(i_0+3)=2\times(i_0+2)+(i_0+3) ((i0+2)+(i0+2))+(i0+3)=2×(i0+2)+(i0+3)
- 类型转换
static_cast
:可以代替C风格的类型转换实现基本类型转换;可以转换父子关系类型的指针,但是可能不安全;不相关类型的指针无法转换dynamic_cast
:只能用于指针间的类型转换,需要继承关系。子类指针可以直接转换为父类指针;而父类指针转换为子类指针时,只有当一个父类指针指向一个子类对象,并且父类指针包含虚函数时才会成功,否则返回空指针,如果是引用则抛出异常const_cast
:可以在转化过程中增加或删除const属reinterpret_cast
:可以将一种类型的指针直接转化为另一种类型的指针或者整数,不论两个类型是否有继承关系。经常用在不同函数指针之间的转换
宏定义和内联
- inline、、
内存分配和sizeof()
- 综合例子:
// 申请的变量 "前缀地址"~所占内存大小~起始地址~"结束地址"
struct T1
{
char a; // 0 1 0 1
short b; // 1 2 2 4
int c; // 4 4 4 8
double d; // 8 8 8 16
}
//占空间最大的基础类型:double(8)
//sizeof(T1)=16;//大等于16最小的8的倍数(内存补齐)
struct T2
{
int a; // 0 4 0 4
double b; // 4 8 8 16
short c; // 16 2 16 18
char d; // 18 1 18 19
}
//占空间最大的基础类型:double(8)
//sizeof(T2)=24;//大等于19最小的8的倍数(内存补齐)
-
类中的变量进行内存分配
-
结构体变量第一个变量的_起始地址为0_
-
组成结构体的基本类型变量在申请空间时_起始地址为该类型所占字节的整数倍的地址_
-
*手动对类中的变量进行内存分配设置
struct T_ { int a:8; //设置占用空间为 8位( 8b即1B) int b:16; //设置占用空间为16位(16b即2B) int c:41; //设置占用空间为41位(41b占6B,没满) int d:32; //设置占用空间为32位(32b即4B) } //书P86
-
-
sizeof()
- sizeof不允许计算结构体中某个域成员占用的空间(
sizeof(node.val)) - sizeof(T_)结果为T_中占空间最大的基本类型的大小的整数倍(内存对齐)
- sizeof不允许计算结构体中某个域成员占用的空间(
-
指针相关的内存分配
- 申请释放
//C: int * p = NULL; p = ( int * ) malloc( sizeof(int) * 10 ); //开一个有10个元素的int数组 free( p ); p = NULL; //赋值NULL避免野指针,下同 //C++ int * p = new int(10); //新建并指向int变量空间(初值为10) delete p; p = NULL; int * p = new int[10]; //新建并指向int数组的空间(元素个数为10) delete p; p = NULL; T_ * p = new T_(); delete p; p = NULL;
- 【P90开始】
main()前后
- 外部初始化构造会在main()之前执行
class OutTest
{
public:
OutTest(){
cout<<"OutTest begins"<<endl;}
};
class InTest
{
private:
static OutTest innerObj;
//InTest(){cout<<"InTest begins"<<endl;}
};
OutTest outObj;
OutTest InTest::innerObj;
int main()
{
cout<<"Main begins"<<endl;
}
/*输出:
OutTest begins
OutTest begins
Main begins
*/
atexit(func);
:注册func()
函数,被注册的函数将在当前函数退出时执行(必须是无参数的void类型函数);如有多个函数,从最后一个被注册的函数开始执行(类比栈)
模版与泛型编程(第15章)
模版
template<typename T_,...>
修饰函数/类尽量少使用操作符,比如能只使用小于号(<)就不使用大于号(>)
- 函数模板
//模板(宏观模板)
template<typename T1,typename T2>
class Test
{
public:
Test(T1 a,T2 b):
a(a),b(b){
cout<<"normal"<<endl;}
private:
T1 a;
T2 b;
};
//运用宏观模板创建的模板
template<>
class Test<char,int>
{
public:
Test(char a,int b):
a(a),b(b){
cout<<"full"<<endl;}
private:
char a;
int b;
};
//运用宏观模板创建的模板
template<typename T>
class Test<T,char>
{
public:
Test(T a,char b):
a(a),b(b){
cout<<"partial"<<endl;}
private:
T a;
char b;
};