C++修炼篇:01 从C到C++的升级

引言:本文意在完成一场从C到C++世界的平滑过渡,因此要求读者应具备一定的C语言基础功底。

文章向导

  • C与C++的关系
  • C++做了哪些升级?

一、C与C++的关系
C与C++的关系并不能简单地概括为仅多了两个+号而已,两者实际上既有区别又有联系,且并无所谓的何者好坏之说。简单说来,C++其实是一种更好的C语言,只不过两者适用场景并不相同。
这里写图片描述
由上图可知,C++继承了C的所有特性,也就是完全地兼容C语言。同时,C++在C的基础上提供了更多的语法和特性(++的由来:类型加强、函数加强)。C++所要达到的目标是运行效率与开发效率的同一。

二、C++做了哪些升级?

1.更为强调语言的实用性

int c = 0;

for(int i=1; i<=Numoftask; i++)
{
    for(int j=1; j<Numoftask; j++)
    {
        c += i * j;
    }
}

上面的程序片段是C++中的常见写法,与C语言(标准规范下)中的变量必须定义在作用域开始的位置处相比,C++则显得更为灵活:所有的变量都可以在使用时再定义,这点正如上面的循环变量i和j。

2.C++编译器独特的优化方式
C++中依然支持register关键字(但实际只是为了兼容C,效果上来看纯属鸡肋),但与C语言相比有着如下的区别:

  • C语言无法获取register变量的地址,而C++却能够做到。
  • C++编译器发现程序需要取register变量的地址时,register对变量的声明将会无效。

另外,在C语言中重复定义多个同名的全局变量是合法的(因为此时多个同名的全局变量最终会被链接到全局数据区的同一个地址空间上),但在C++中则不允许重复定义多个同名的全局变量。
为了理解上述所说,不妨看下面这样一个实际的例子:

#include <stdio.h>

int g_v;
int g_v; //在c++中,此行会报错

int main(int argc, char *argv[])
{
    printf("Begin...\n");

    int c = 0; //在C中,此处会报错

    for(int i=1; i<=3; i++) //在C中,此处会报错
    {
        for(int j=1; j<=3; j++)
        {
            c += i * j;
        }
    }

    printf("c = %d\n", c);

    register int a = 0; //在C中,此处会报错

    printf("&a = %p\n", &a); //在C中,此处会报错
    printf("End...\n");

    return 0;
}

3.struct关键字的加强

/*C语言中的结构体书写*/
typedef struct _tag_student Student;

struct _tag_student
{
    const char* name;
    int age;
};

/*C++中的结构体书写*/
struct Student
{
    const char* name;
    int age;
}

上面展示的为C与C++中的结构体等价写法,可明显发现两者的区别:-C语言中struct定义的标识符并不是一种新的类型,而C++中的struct却用于定义一种全新的类型。

4.隐式声明与函数参数
首先,应该明确的是C++中所有的标识符都必须显示声明类型,即在C++中不应该写出如下的代码:

扫描二维码关注公众号,回复: 1120951 查看本文章
f()
{
    printf("i = %d\n", i);
}

上面的函数f()在C语言中表示默认返回值为int,且可接收任意多的参数,但在C++中这样写是没法通过编译的。另外,值得注意的是C++中 int f()和int f(void)具有相同的意义。

5.const关键字的升级
这里写图片描述
上图对比了const关键字在C语言与C++中的异同之处,为了更好的理解图中的结论,请看如下两个示例。

/*test.c*/
#include <stdio.h>

int main()
{
    const int c = 0;
    int* p = (int*)&c;

    printf("Begin...\n");

    *p = 5;

    printf("c = %d\n", c);  //5
    printf("&p = %p, p = %p, &c = %p\n", &p, p, &c); 
    printf("*p = %d\n", *p); //5
    printf("End...\n");

    return 0;
}
/*test.cpp*/
#include <stdio.h>

int main()
{
    const int c = 0;
    int* p = (int*)&c;

    printf("Begin...\n");

    *p = 5;

    printf("c = %d\n", c);  //0
    printf("&p = %p, p = %p, &c = %p\n", &p, p, &c); 
    printf("*p = %d\n", *p); //5
    printf("End...\n");

    return 0;
}

这里主要分析第二个例子,也就是C++中的情形。首先看下完整的运行结果:
这里写图片描述
从图中可以明确看到编译器给const常量c分配了存储空间,但却并未使用其存储空间中的值。要理解这点则需明白之前提及的“符号表(编译器的一种数据结构)”,C++中定义的const常量,编译器会将其存入符号表中,当要使用常量时则直接从符号表中取值进行替换,但为了兼容C语言可能会为其分配存储空间,但却不会使用其中的值。有点绕?那不妨看看下面这张草图:
这里写图片描述

Notes:实际上还有其他的升级方面,但这会牵涉到C++独有的知识点,因此笔者想将其放在后续的内容中来论述。

参阅资料
C++ Primer Plus(第6版)
狄泰软件学院-C++深度解析教程

猜你喜欢

转载自blog.csdn.net/a574780196/article/details/80501250