为什么 C 语言没有被 C++ 取代? - 知乎
随着 C++ 的不断有新标准出炉,编译器在 C++ 背后做的事情越来越多,相比较而言 C 语言编译器在背后就老实许多。
作者:知乎用户
链接:https://www.zhihu.com/question/266995763/answer/2751818359
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
如果一个项目如果对内存和编译后的机器指令做精准控制,那么应该优先选择 C 而不是 C++,C++ 编译器在背后插入了太多的指令。举两个例子:
class A { public: A() {} ~A() {} }; int main() { A a; return 0; }
这个例子说明了在 C++ 中一个对象出了其作用域(这里是 a),会自动调用其析构函数,这是编译器自动加入的:
A a; 00007FF71E2918DD lea rcx,[a] 00007FF71E2918E1 call A::A (07FF71E291302h) return 0; 00007FF71E2918E6 mov dword ptr [rbp+0E4h],0 00007FF71E2918F0 lea rcx,[a] 00007FF71E2918F4 call A::~A (07FF71E291258h) ;编译在这里自动插入调用类A的析构函数 00007FF71E2918F9 mov eax,dword ptr [rbp+0E4h] }
再比如假设 A 类有一个实例方法 f,编译器的调用 A 方法的实现是编译器自动插入了一个 this 指针作为方法的第一个参数:
class A { public: A() {} ~A() {} void f(int a, int b) {} }; int main() { A a; a.f(1, 2); return 0; }
汇编代码如下:
A a; 00007FF7157D193D lea rcx,[a] 00007FF7157D1941 call A::A (07FF7157D1311h) 00007FF7157D1946 nop a.f(1, 2); ;由于函数调用方式是__thiscall, 00007FF7157D1947 mov r8d,2 ;所以参数从右往左入栈,这是第一个参数2 00007FF7157D194D mov edx,1 ;这是第一个参数的1 00007FF7157D1952 lea rcx,[a];这是对象a的地址,即this指针 00007FF7157D1956 call A::f (07FF7157D110Eh) ;调用a的方法f return 0; 00007FF7157D195B mov dword ptr [rbp+0E4h],0 00007FF7157D1965 lea rcx,[a] 00007FF7157D1969 call A::~A (07FF7157D1267h) 00007FF7157D196E mov eax,dword ptr [rbp+0E4h]
以上,在 C 编译器中不会有的,C 编译器一般不会偷偷插入开发者不知道的指令,你写了什么代码,对应的机器指令和你预期的所差无几。这就是为什么像内核以及一些对性能和内存利用率要求比较高的项目需要使用 C 而不是 C++。