这里记录一下在找工做前的复习过程当中那些让我怀疑我是否是真的学过计算机的知识点。。html
cout << boolalpha << (1 == 2);
输出false
参考连接:http://www.cnblogs.com/devymex/archive/2010/09/06/1818754.html数组
const
在*
的左侧,如 const int *a
或int const *a
,不能改变指针a
指向的内容的值const
在*
的右侧,如 int* const a
,指针a
自己为常量,不能改变a
的指向ide
我的以为把const
放在类型符号后边意义更明确一些。。函数
在类中,修饰为mutable
的成员变量能够被修饰为const
的成员函数修改优化
class A { public: mutable int a; void set_a(int n) const { a = n; } };
sizeof()结果由编译时肯定,()内代码不被执行ui
int a = 0; sizeof(a = 1);
a
的值不会被改变this
注意,引用也是要占用内存空间的,内容是被引用的变量的地址,同指针同样spa
struct st1 { int a; int &b; st1(int n) : a(n), b(a) {} }; struct st2 { int a; int *b; st2(int n) : a(n), b(&a) {} }; st1 s1(10); st2 *ps2 = reinterpret_cast<st2*>(&s1); cout << *(ps2->b); // 10
参考连接:http://blog.csdn.net/thisispan/article/details/7456169.net
int *a[10];//包含十个元素的数组,数组元素是整型指针 int *(a[10]);//同上 int (*a)[10];//指向具备十个整型元素的数组的指针 int (*a)();//指向无参数且返回整型的函数的指针 int (*a[10])();//包含十个元素的数组,数组元素是指向无参数且返回整型的函数的指针 int (**a)[10];//指向一维数组指针的指针,数组具备十个整型元素 int *(*a)[10];//指向一维数组的指针,数组具备十个整型指针元素 int (*(*a)(int))();//指向具备一个整型参数且返回函数指针的函数的指针,返回的函数指针指向无参数且返回整型的函数
int a[5] = {1, 2, 3, 4, 5}; int *p = (int*)(&a + 1); cout << (int)*(p - 1);
输出为5
数组名a
是指向数组第一个元素的指针,&a
是指向数组的指针,虽然两个指向同一个地址,可是&a + 1
其实是将指针向后移动了sizeof(a),也就是20个字节,与a + 1
移动一个字节不一样
在这里p
相似于二维数组线程
this
指针其实是类成员函数的第一个参数,由编译器自动添加,经过寄存器传递,整个生命周期同函数参数一致
删除vector
等连续空间的容器元素后,相应迭代器会失效
struct
与class
除了默认访问控制不一样之外,其余彻底相同。struct
默认访问控制是public
,class
默认访问控制是private
除开父类构造函数,成员变量初始化按照成员变量在类中申明的顺序执行,与初始化列表顺序无关
除了虚函数和静态成员函数,其余函数能够是内联的,包括构造函数和析构函数。
事实上,若是成员函数在类申明中定义,那么默认是内联的。类申明外定义的函数能够用inline
修饰为内联的。但须要注意的是,内联函数是内部连接的,只能在本文件内被调用。
//A.h class A { public: A() { cout << "A()" << endl; } inline virtual ~A() { cout << "~A()" << endl; } inline void func1() { cout << "func1" << endl; } void func2(); }; //A.cc inline void A::func2() { cout << "func2" << endl; } //main.cc A *a = new A; a->func1(); a->func2();// 编译失败 delete a;
class A { public: int m; A(int n) : m(n) {} A(float n) : m(n * 2) {} }; A a = 10; // a.m == 10 A a = 10.0;// a.m == 20
单个参数的函数若是不添加explicit,会发生隐式的类型转换
私有继承与保护继承的派生类不能称为子类,由于派生类并不能完成父类能作的全部事情
参考连接:http://www.oschina.net/translate/cpp-virtual-inheritance
将构造函数申明为private或纯虚类(抽象类)
将析构函数申明为private
重载new运算符为private
将复制构造函数和赋值函数声明为private,或者声明为 = delete
加final关键字
其余方法:http://blog.chinaunix.net/uid-26983585-id-4373697.html
static_cast和C语言里的强制类型转换类似,不过编译时会作类型检查,只有相关的类型才能转换,不然编译错误
dynamic_cast在程序运行时根据对象的虚表进行向上或者向下转换。转换指针失败时,返回nullptr,转换引用失败时,抛出异常
然而Google并不建议使用dynamic_cast,参考:http://www.zhihu.com/question/22445339
const_cast去除对象的只读属性
reinterpret_cast不作二进制转换,仅仅是从新解释二进制块,经常用在偏底层的操做上,可移植性稍弱
class A { public: static int m; int n; void func1() { cout << this << ' ' << m << endl; } void func2() { cout << this << ' ' << n << endl; } static void func3() { cout << m << endl; } }; int A::m = 10; A *a = 0; a->func1();// 0 10 a->func2();// crash a->func3();// 10 A::func3();// 10
若是对象指针指向错误的地址,对象成员函数仍然能够被调用,可是不能访问非静态成员变量。这里同时也将静态成员函数拿出来比较。
想想,假如成员函数是虚函数,结果还会同样么?
struct A { int a:1; int b:2; int c:3; }; cout << sizeof(A);// 4
参考连接:http://www.cnblogs.com/bigrabbit/archive/2012/09/20/2695543.html
模块
函数
类
起到的做用有什么异同
volatile关键字告诉编译器不要优化被它修饰的变量,这个变量可能在编译器控制范围外发生改变,好比中断或者其余线程
注意下面这个例子
int func(volatile int *p) { // return (*p) * (*p); // wrong int temp = *p; return temp * temp; }
不一样类型的变量参与混合运算时,全部变量将会转换为同一类型,为了避免丢失精度,老是转换为长度更长的变量
在32位机器上,char,short老是转换为int,float老是转换为double
通常状况下,不用关注转换的问题,可是考虑下面一个例子:
signed char a = 0xe0; unsigned int b = a; cout << int(a) << ' ' << b;
结果 -32 4294967264
由于在a赋值给b时,a要提高为32位的unsigned int型。然而a是负数,在提高长度时高位将用1
来补全,因而a被提高为0xffffffe0
。赋值后,b的值为0xffffffe0
,因此做为无符号整型输出为4294967264
const成员变量必须在构造函数初始化列表中被初始化。
class A { public: const int m; A(int n) : m(n) {} };
static const成员变量能够在声明时初始化
class A { public: static const int m = 0; A(int n) {} };
static成员变量不能在声明时初始化,也不能在构造函数初始化列表中初始化,只能在类外申明并初始化
C++ 11已经支持非静态(static const例外)成员变量声明时初始化,自定义类型不能执行带参数的构造函数
C和C++程序中,函数的调用有多种方式,能够经过在函数声明时加上__stdcall
,__cdecl
,__fastcall
来显式指定
不一样的函数调用方式体如今参数传递方式,编译后函数命名方式,函数返回时栈清理方式的不一样。
参考连接:http://www.cnblogs.com/zhangchaoyang/articles/2725189.html
简单的说,具备变长参数的函数在调用时(__cdecl方式),编译器按正常的方式将参数从右到左入栈,函数内部再经过指针根据参数类型依次从栈中将参数取出
以printf("%c,%d", 'A', 10);
举栗
由于参数从右到左进栈且栈是从高地址到低地址生长的,因此此时内存是这样的:
低地址<<| 4 byte | 1 byte | 4 byte |>>高地址 |"%c,%d"的地址| 'A' | 10 |
首先printf
函数的第一个参数不是变长参数,这里咱们假设这个参数叫str
,它是指向"%c,%d"
的指针。有了str
,咱们天然就知道了变长参数的起始地址是&str+1
,而后再根据"%c,%d"
,咱们知道了变长参数有两个并且类型分别为char
和int
,因而咱们就能够依次获得这两个变量辣
参考连接:http://www.cnblogs.com/chinazhangjie/archive/2012/08/18/2645475.html
经过const_cast能够去除read-only属性,可是编译时编译器仍将使用到const变量的地方直接替换为初始化的那个值,相似于宏
int const a = 1; int *p = const_cast<int*>(&a); *p = 2; cout << a << " " << *p; // 输出: 1 2
加override
,貌似又是C++ 11的关键字
class A { public: virtual void func(int n); } class B : A { public: virtual void func(int n); // 不要这样,若是参数写错了,至关于声明了重载函数 void func(int n); // 同上 void func(int n) override; // 强制重写基类函数,若是参数或返回值与基类虚函数不一致,编译器报错 }
未完......