C++继承了全部的C特性,而且提供了更丰富的语法和特性(OOP支持、模板支持等),而且拥有和C语言一样出色的运行效率。针对C语言的固有问题,C++作出了以下的升级:函数
在C99标准以前,C函数中的全部变量定义都必需要写在函数的开头:优化
int main() { return 0; }
void func() { int a, b, i; // 运算代码... a = 10; // 运算代码... b = 20; // 运算代码... for(i = 0; i < 10; i++) { // 运算代码... } }
这样作的问题在于:若是函数很是复杂,须要使用的变量不少,那么很难根据上下文来判断变量的含义,对于代码的书写和阅读都很不利。所以,自C99标准开始,C支持在变量须要使用时再定义和初始化:设计
void func() { // 运算代码... int a = 10; // 运算代码... int b = 20; // 运算代码... for(int i = 0; i < 10; i++) { // 运算代码... } }
而对于C++,在语言设计之初就已经支持了这个特性。全部的对象均可以在函数中的任意位置定义。code
在C语言中,register
关键字用于请求编译器将变量直接定义在寄存器中(编译器可能会根据实际状况忽略这个请求)。然而,这个功能在C++中是一个鸡肋,所以大多数C++不会针对register
关键字进行特殊优化。对象
int main(int argc, char *argv[]) { register int a = 0; int *pa = &a; // C语言不容许这样作,但C++能够。 return 0; }
对于老式的C语言编译器(好比BCC编译器),容许定义同名的全局变量,而且将它们连接到同一块内存上。虽然一些现代化的C编译器(例如gcc, VC)一样不容许这样作,可是这仍然是C的一个黑暗地带。所以,C++彻底禁止了这样的作法。如今,C++中的同名的全局变量必定会引起编译错误。继承
int g_v = 1; double g_v = 2; // 编译错误: 定义同名的全局变量。 int main(int argc, char *argv[]) { return 0; }
在C语言中,struct
关键字仅仅用于将多个其余数据类型组合在一块儿,采起必定的对齐方式占用一块连续的内存空间。然而,它定义的只是一个标识符,没法直接使用这个标识符来定义变量,而必需要使用类型别名的方式来为这个标识符定义类型名称。C++针对struct
作了重要的扩充。如今,struct
被用来定义类类型,不只直接定义一个新类型,还支持类相关的写法(更多的被用于定义POD
(Plain Old Data)类型)。内存
struct my_struct { int a; float b; double c; }; int main(int argc, char *argv[]) { // C风格的变量定义。 struct my_struct a; // C++风格的对象定义。 my_struct c; return 0; }
在C中,函数声明中的参数列表若是为空,则意味着该函数能够接受任意多的实参;而在C++中,这种写法与void等价:编译器
int func() { //... return 0; } int main(int argc, char *argv[]) { func(1, 2, 3, 4/*....*/); // C语言容许这样作,这些变量在函数调用时被压栈。 // C++语言不容许这样作,由于参数列表被推断为void。 return 0; }
C语言中容许使用函数的默认返回类型和变量的默认类型,然而对此C++有更严格的要求,必须显示地声明变量的类型,或者使用自动类型推断(C++11)。编译
// C语言容许这样作,默认的返回类型为int。 // C++语言不容许这样作,必须显示地指定返回类型,或者使用自动类型推断。 func() { return 5; } // C++容许的作法 int func() // 显示指定返回类型 { return 5; } auto func() // 自动推断返回类型(C++11) { return 5; } decltype(auto) func() // 自动推断返回类型(C++11) { return 5; }