函数指针
函数指针本质还是指针,可以用来调用函数和传递参数。声明方式:type (*name)(形参表)
,另外常常与typedef结合使用。比如这样使用:
int fun(int a,int b)
{
return a+b;
}
int (*pf)(int) = fun;
cout<<pf(3,4)<<endl; // 7
使用typedef:typedef int(*PF)(int a,int b);
定义了一个函数指针,函数返回值是int,有两个形参。可以理解为typedef int (int a,int b) *PF
。使用:
PF foo = fun;
cout<<foo(3,4)<<endl; // 7
其实有多种调用方式,记住一种就好,其他不常用。
参考:函数指针多种调用方式
指针函数
数组
char a[]={1,2,3,4};
的定义是正确的,按ASCII处理,97对应的是a
。
数组声明时,下标只能是常量,常量表达式。
const int a=1,b=3; //不能去掉const
int aa[a+b];
指针数组和数组指针
int* p[10]
是一个指针数组,数组中每个元素都是一个int型的指针。其中[]优先级比*
高。
int (*p)[10]
是一个数组指针,指针指向列长度为10的二维数组的第一行的行地址。p+1
表示第二行的首地址。p = p[0][0]; (p+1)=p[1][0]; ((p+i)+j) = p[i][j];
其实二者区别就是*
和int结合还是和p结合,(int*) p[10]
是10个指针。
int n[2][3] = {10,20,30,40,50,60};
int (*p)[3];
p=n;
std::cout<<p[0][0]<<","<<*(p[0]+1)<<","<<(*p)[2]<<endl;
p是一个指针,指向了二维数组的行首地址,p[0][0]是n[0][0]。直接在p上偏移就是行,在*p
上偏移就是列。*(p[0]+1)
实际就是*(*p+1)
,在列上偏移,就是p[0][1]=20。(*p)[2]
其实就是p[0][2]
为30。可以如下图理解:
常用sizeof的值
类型 | 32位 | 64位 |
---|---|---|
char | 1 | 1 |
int | 4 | 4或8 |
long | 4 | 4 |
float | 4 | 4 |
double | 8 | 8 |
指针 | 4 | 8 |
也就是只有long和指针在不同平台下的值不同。
标签
int main(){
http://www.taobao.com
cout<<"welcome"<<endl;
}
这是C++一个几乎没人用的语法:标签,常和goto搭配使用。一个标识符后加冒号就构成了标签,后面的//www.taobao.com是注释,不起作用。
typedef
typedef常用来定义一个标识符及关键字的别名,它是语言编译过程的一部分,但它并不实际分配内存空间,例如typedef int INT
。
#define
在预处理阶段处理,难以发现潜在的错误,使用:#define INT int
scanf
printf和scanf不是C语言提供的,而是库函数。
scanf只能控制长度,不能控制精度,printf都能控制。比如scanf("%7f",&a)
正确,但scanf("%7.4f",&a)
是错的。
如果格式控制字符串有非格式字符,也应当输入相应非格式字符,也就是scanf什么样,也输入什么样的代码。
int a,b;
scanf("a=%d,,b=%d",&a,&b); //必须是引用
printf("%d.....%d\n",a,b);
输入a=12,,b=34
然后回车,否则结果会出错。
例外情况是,输入多个数值时,可以用空格或回车做间隔。
int a,b;
scanf("%3d%4d",&a,&b);
printf("%d.....%d\n",a,b);
输入123456789
,结果是123.....4567
,因为有长度控制。如果希望结果是12.....345
,可以输入12 345
。
类型安全
能进行类型强制转换的语言不是类型安全的,C++显然不安全,但java和c#是安全的。
构造函数执行顺序
一个类有基类,内部有一个其他类的成员对象,构造函数的执行顺序是:基类构造函数→成员对象的→自己构造。即先父母,后客人,最后自己。
不用初始化即可自动获得初值0的变量有全局变量和静态局部变量(不是类成员变量)
如何实现一个不能被继承的类
class B final {
public:
B(int a) {
}
};
加final关键字,这是C++ 11的特性。
C++11有哪些新特性?
lambda,线程库,智能指针,auto,final