美文网首页我爱编程
[转]你可能不知道的C++(一)

[转]你可能不知道的C++(一)

作者: babybus_hentai | 来源:发表于2016-04-08 17:37 被阅读87次

    此为《你可能不知道的C++》的第一部分,讨论C&c++,编译单元以及对象

    C++&c##

    C++ 是 C 的超集,但是 C++ 中的子集 C 跟原始的 C 还是有点不一样。

    结构 & 联合###

    • C 的结构(struct)不是一种类型,使用时得带着关键字struct,一般用typedef来避免这种不便。
    • C++ 的结构几乎等价于类,只是缺省的访问权限为public而非private。
    • C++ 的联合(union)可以有成员函数,甚至可以有构造和析构函数。

    不带参数的函数###

    对 C 来说,一个不带参数的函数意味着可以接受任意参数。所以void f()就相当于void f(...),而下面三个函数指针类型中:
    <pre>typedef void (foox)();
    typedef void (
    foo1)(int);
    typedef void (*foo2)(void);
    </pre>

    foo1和foo2可以隐式地转型为foox,就好比可以从int或char隐式地转型成void*。

    要想让一个 C 函数真正没有参数,得用void:
    <pre>void foo(void);</pre>

    对 C++ 来说,一个不带参数的函数就是指不接受参数。往参数列表里放void是多余的。

    提升void*###

    C 会自动提升(promote)void
    <pre>int
    pi = malloc(sizeof(int));</pre>

    函数malloc返回void,赋值给int时不需要显式转型。而 C++ 必须显式转型:
    <pre>int* pi = static_cast
    (int*)(malloc(sizeof(int)));</pre>

    CONSTS###

    C++ 允许 consts 用在常量表达式中:

    <pre>const int MAX = 4;
    int a[MAX + 1];
    switch (i) {
    case MAX:
    ...
    }</pre>

    而 C 则必须使用宏:
    <pre>#define MAX 4</pre>

    引一段《C++ 的设计和演化》的原文:
    (Bjarne Stroustrup, The Design and Evolution Of C++, 3.8)

    In C, consts may not be used in constant expressions. This makes consts far less useful in C than in C++ and leaves C dependent on the preprocessror while C++ programmers can use properly typed and scoped consts.
    </br>

    C 的 consts(特指用 const 关键字修饰的常量)不可以用在常量表达式中。这让 C 的 consts 远不如 C++ 的有用,也让 C 依赖于预处理器,而 C++ 程序员则可以使用有适当类型和作用域的 consts。

    前置声明###

    C 代码块中,所有声明必须出现在任何程序语句之前,比如函数定义时,先声明所有局部变量:
    <pre>
    void foo() {
    int ival, p;
    /
    … */
    }
    </pre>

    而 C++ 的声明,诸如int ival;,其自身就是一个程序语句,也因此可以出现在程序文本中的任何位置。

    编译单元##

    C/C++ 中的一个源文件(.c, .cpp, .cc)就是一个编译单元(compilation unit)。
    头文件(.h, .hpp)不是编译单元,是不能单独编译的。

    源文件经过预处理,先搞定下面这些东西:

    • 宏:包括用户定义的,和预定义的(__cplusplus, FILE, ...)
    • 包含语句:源文件中的include语句全部展开
    • 条件编译: #if, #else, #ifudef, ...#error, #warning, ...

    预处理过的源文件,经过编译,生成对象文件(.o, .obj)。对象文件经过链接或打包,生成可执行文件或程序库。虽然这里的步骤不太严格,但是大抵就是这样。

    如果你对预处理的结果很感兴趣,可以试试编译器的预处理命令:gcc -E (GCC),cl /E or /P (VC)。

    对象##

    这里所说的对象(object),泛指一切类型的实例,不只是类的实例。

    关于对象,我们将探讨以下几个方面:

    • 对象的大小(size)
    • 按存储(storage)分类的对象
    • 聚合(aggregate)

    对象的大小###

    先来考虑几个问题:

    • sizeof是一个函数吗?
    • 你知道sizeof(int), sizeof(long)各为多少吗?
    • 为什么应该用size_t?

    <strong>size_t</strong>

    标准库里到处都是size_t的身影:
    <pre>
    void *malloc(size_t n);
    void *memcpy(void *s1, void const *s2, size_t n);
    size_t strlen(char const *s);
    </pre>

    回到前面的问题,不难理解以下几点:

    • size_t是sizeof返回值的类型
    • size_t是一个typedef
    • sizeof不是一个函数,它是一个编译时操作符
    • size_t能够表示任何类型理论上可能的数组的最大大小

    其实,size_t一般就是unsigned int的typedef,那为什么不直接用unsigned int?在IP16或IP32平台上(即int和指针大小一致时),确实没有问题,但I16LP32就不行了。此外,直接用unsigned long固然没错,但毕竟得多花了几个字节,稍微有点浪费了。反正只要用size_t,你就可以同时得到正确性和可移植性。

    <strong>数据对齐</strong>

    请问mixed_data的大小是多少?是 8 吗?
    <pre>
    struct mixed_data {
    char data1;
    short data2;
    int data3;
    char data4;
    };
    </pre>

    在 32 位 x86 平台上编译后的样子:
    <pre>
    struct mixed_data {
    char data1;
    char padding1[1];
    short data2;
    int data3;
    char data4;
    char padding2[3];
    };</pre>
    为了数据对齐,编译器塞了一些边角料进去,最终的大小为 12

    <strong>按存储分类的对象</strong>
    C/C++ 的对象,按存储类型分为以下几种:

    • 自动的(auto, register)</br>
    • 静态的(static)
      自由存储的(free-store)
      关键字auto有点多余,下面两条声明语句其实等价,b前面的auto加不加一个效果:
      <pre>
      {
      int a;
      auto int b;
      }
      </pre>
      到了 C++11,auto这个关键字就被拿来另作他用了:auto可以让编译器从变量的初始化上自动推断出它的类型:
      <pre>auto a = std::max(1.0, 4.0); // 编译器推断出 a 的类型为 double</pre>

    聚合###

    首先,什么叫聚合?

    对 C 来说,数组和结构是聚合。

    对 C++ 来说,除了数组外,满足以下条件的类(或结构)也是聚合:

    • 没有用户声明的构造函数
    • 没有private或protected非静态数据成员
    • 没有基类
    • 没有虚函数

    所以,下面几个类型都是聚合:
    <pre>
    int[5];

    struct person {
    std::string name;
    int age;
    };

    boost::array;
    </pre>

    <strong>第一部分完。</strong>
    原文地址

    相关文章

      网友评论

        本文标题:[转]你可能不知道的C++(一)

        本文链接:https://www.haomeiwen.com/subject/vsvvlttx.html