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

此为《你可能不知道的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>
原文地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容