C++
兼容C
,但同样的东西,在C++
和C
中的表现可能不同,下面总结了一些。
1、函数空参
int f();
函数空参时,C
表示任意参数,C++
表示没有参数。
int f(void);
C
表示没有参数时使用void。
2、函数参数标识符
int f(int a);
int f(int);
声明函数时,C
和C++
都可以省略标识符。
int f(int a) {}
int f(int) {} // C++
定义函数时,C++
可以省略标识符,C
不可以省略标识符。
3、函数返回类型
int foo();
foo(); // C
C++
函数原型必须指明函数的返回值类型,在C
中,如果省略返回值,表示默认为整型。
4、函数声明与定义
void foo(float a) {}
foo(100);
C
和C++
中编译函数的方式是不同的,以上面的foo函数为例,C
编译出来的符号信息就是个简单的函数名,即foo,而C++
还包括参数的类型信息,即_Z3fooi,_Z是一个固定的标识符,后面的3表示其后的函数名foo的长度为3,最后的i表示函数的参数类型为int,所以C++
支持函数重载。调用没有声明的函数在C
中是可以的,但是在C++
中不可以。C
中虽然允许调用没有声明的函数,但不声明很可能会带来很难发现的bug,以上面的foo函数为例,参数类型为float,但函数传递进来的参数类型为int,如果调用之前声明了这个函数的原型,那么int类型会自动提升为float,没有问题,但如果没有声明的话,编译器认为foo函数原型的参数类型就是int而不进行类型转换,因为C
函数的符号信息不包括参数的类型,自然也发现不了这个问题,所以潜在的问题就来了。
5、变量定义
int i; for (i = 0; i < 100; ++i) {}
for (int i = 0; i < 100; ++i) {} // C++
C/C++
都要求变量在使用前必须定义,但C
强制在作用域的开始处就定义所有的变量,以便在编译器创建一个块时,能给所有这些变量分配空间,而C++
允许在在作用域的任意地放定义变量,所以可以在正好使用它之前定义,甚至还可以在if语句的条件表达式、switch的选择器语句、for循环和while循环的控制表达式内定义变量。
6、头文件include
#include <stdio.h>
#include <cstdio> // C++
#include <iostream> // C++
include头文件的方式以标准IO库为例,见上面的例子,如果在同一C++
程序中混用两种形式,即带头文件后缀和不带头文件后缀,会遇到某些问题。
7、类型转换
int a = 100;
float b = (float)a;
float b = float(a); // C++
除了隐式类型转换外,更多的是显式类型转换。在C
中,将转换的类型放在括号中,而在C++
中,可以将转换的变量放在括号中。
int a = 0;
void *b = &a;
int *c = b; // ok in C, but ng in C++
int *d = (int*)b; // ok in both C and C++
对于void指针的用法也是不同的,见上面的例子。另外,C++
还提供了四个特有的类型转换,请参照C++】深入理解C++的各关键字一文中的cast说明。
8、复合类型
struct A a;
enum B b;
union C c;
A a; // C++
B b; // C++
C c; // C++
typedef struct {} A;
A a;
b++; // ok in C, but ng in C++
C
中的struct、enum、union定义变量时必须同时给出关键字,而C++
中可以省略这些关键字,在C
中也可以省略这些关键字的方法是使用typedef。C
中的enum是直接与int关联的,可以进行运算,而C++
则不行,类型检查更严。另外,C++
还引入了class,是struct的升级版,提供了成员函数等更多强大的功能。
9、指针与引用
int foo(int *a);
int foo(int &a); // C++
在C
中,通过函数修改函数外部的变量时,函数的参数类型需要使用指针,按地址传递,而不是普通类型的按值传递,在C++
中,除了指针之外,又引入了引用类型,可以完成同样的功能。
在函数参数中使用常量引用特别重要,这时因为我们的函数也许会接受临时对象,这个临时对象是由另一个函数的返回值创立或由函数使用者显式创立的,临时对象总是不变的,因此如果不使用常量引用,参数将不会被编译器接受。在效率方面,传值方式需要调用构造函数和析构函数,然而如果不想改变参数,则可以通过常量引用传递,它仅需要将地址压栈。
使用引用时有一定的规则:
1)当引用被创建时,它必须被初始化,指针则可以在任何时候被初始化。
2)一旦一个引用被初始化为指向一个对象,它就不能改变为另一个对象的引用,指针则可以在任何时候指向另一个对象。
3)不可能有NULL引用,必须确保引用是和一块合法的存储单元关联。
10、动态内存
int *p = malloc(sizeof(int));
free(p);
p = malloc(sizeof(int) * 10);
free(p);
int *p = new int; // C++
delete p;
p = new int[10];
delete[] p;
动态内存分配,C
中使用malloc和free,C++
引入了new和delete。
11、const
const关键字的用法请参照C++】深入理解C++的各关键字一文中的const说明。