C++基礎:(1)C++對C的加強

C++對C的加強

1. C++命名空間基本常識

所謂namespace煮纵,是指標識符的各種可見范圍买决。C++標準庫中的所有標識符都被定義于一個名為std的namespace中擂红。

  1. 文件<iostream> 和 <iostream.h>格式不一樣,前者沒有后綴州既,實際上氮凝,在你的編譯器include文件夾中可以看到羔巢,二者是兩個文件,打開文件就會發(fā)現(xiàn)罩阵,里面的代碼是不一樣的竿秆。后綴為.h的頭文件C++標準已經(jīng)明確提出不支持了, 早些的實現(xiàn)將標準庫功能定義在全局空間里稿壁,聲明在帶.h后綴的頭文件里幽钢,C++標準為了和c區(qū)別開,也為了正確使用命名空間傅是,規(guī)定頭文件不使用帶后綴.h搅吁。因此:
  • 1.1 當使用<iostream.h>時,相當于在c中調用庫函數(shù)落午,使用的是全局命名空間,也就是早期的c++實現(xiàn)肚豺;
  • 1.2 當使用<iostream>時溃斋,該頭文件沒有定義全局命名空間,必須使用namespace std; 這樣債能正確使用cout吸申;
  1. 由于namespace的概念梗劫,使用C++標準庫的任何標識符時,可以有以下三種選擇:
  • 2.1 直接指定標識符截碴。例如std::ostream 而不是ostream梳侨。完整語句如下:
    std::cout << std:hex << 3.4 << std::endl;
  • 2.2 使用關鍵字。using std::cout; using std::endl; using std::cin; 以上程序可以寫成
    using std::cout;
    using std::endl;
    using std::cin;

    cout << std::hex << 3.4 << endl;
  • 2.3 最方便就是using namespace std; 例如:using namespace std; 這樣命名空間std內定義的所有標志符都有效(曝光)日丹。就好像他們被聲明為全局變量一樣走哺。那么以上語句可以如下寫:
    using namespace std;
    cout << hex << 3.4 <<endl;

因為標準庫非常龐大,所以程序員在選擇的類的名稱或者函數(shù)名時哲虾,就有可能和標準庫的某個名字相同丙躏。所以為了避免這種情況所造成的名字沖突择示,就把標準庫中的一切都放在名字空間std中。

但是晒旅,這樣又會帶來一個新問題:無數(shù)原有的C++代碼都依賴于使用了多年的偽標準庫中的功能栅盲,他們都是在全局空間下的。所以就有了<iostream.h> 和 <iostream>等等這樣的文件废恋,一個是為了兼容以前的C++代碼谈秫,一個是為了支持新的標準。 命名空間std封裝的是標準程序庫的名稱鱼鼓,標準程序庫為了和以前的頭文件區(qū)別拟烫,一般不加".h"。

總之蚓哩,標準C++引入關鍵字namespace(命名空間/名字空間/名稱空間/名域)构灸,可以更好地控制標識符的作用域。

既然提高的命名空間這個詞岸梨,不妨把C語言的命名空間和C++的命名空間兩者做一對比喜颁,就會更容易接受C++新標準這么指定使用規(guī)則的緣由:

C里面的命名空間:

  • 在C語言中只有一個全局作用域;
  • C語言中所有的全局標識符共享同一個作用域曹阔;
  • 標識符之間可能發(fā)生沖突半开。

C++提出了命名空間的概念:

  • 命名空間將全局作用域分成不同的部分;
  • 不同命名空間的標識符可以同名而不會發(fā)生沖突赃份;
  • 命名空間可以相互嵌套寂拆;
  • 全局作用域也叫默認命名空間。

案例代碼:

#include "iostream"

// 文件iostream中沒有引入標準的std抓韩,所以需要我們程序員手工寫
using namespace std;

namespace namespaceA
{
    int a = 10;
}

namespace namespaceB
{
    int a = 20;
    // namespace 也支持嵌套
    namespace namespaceC
    {
        struct Teacher
        {
            char name[32];
            int age;
        } ;
    }
}

int main()
{
    cout << "namespace test" << endl; 

    /* using namespace namespaceA; */
    cout << namespaceA::a << endl;
    cout << namespaceB::a << endl;

    using namespaceB::namespaceC::Teacher;
    Teacher t1;
    t1.age = 23;
}

2.“實用性”加強

C語言的變量都必須在作用于的開始位置定義纠永,但是C++更強調語言“實用性”,所有的變量都可以在需要的時候定義谒拴。

3. register關鍵字增強

在C語言中尝江,

  • 1)register關鍵字請求“編譯器”將局部變量存儲于寄存器中;
  • 2)C語言中無法獲得register變量的地址;
    在C++語言中, 1)C++編譯器有自己的優(yōu)化方式英上,即使程序員不使用register也可能做優(yōu)化, 2)C++中可以獲得register變量的地址炭序。
  • PS: 所謂的代碼優(yōu)化,就是如果變量出現(xiàn)在循環(huán)中被重復的使用苍日,那么編譯器在處理代碼時就會把變量的存放在寄存器中惭聂。

早期的計算機比較慢,編譯器不會對代碼進行優(yōu)化相恃,所以使用register來做一個人為地補充辜纲。

C++編譯器除了有自己的優(yōu)化代碼的方式,在發(fā)現(xiàn)程序中需要取register變量的地址的時候,register對變量的聲明變得無效侨歉。

#include "iostream"
using namespace std;

int main()
{
    int nRet = 0;
    register int a = 100;

    printf("&a = %d\n", &a);
    // 上面的語句在C語言中無法編譯通過屋摇,但是C++可以變異成功

    return nRet;
}

4. 變量檢測增強

C語言里面的一個“灰色地帶”:重復定義多個同名的全局變量是合法的;

C++中編譯器不允許定義多個同名的全局變量幽邓,會直接拒絕這種二義性的做法炮温。

int g_a;
int g_a = 100;

void main()
{
    printf("hello world...\n");
}

5.struct類型增強

C語言不認為預先定義的struct是一種數(shù)據(jù)類型,所以我使用typedef來自己定義一個數(shù)據(jù)類型牵舵。

C++中就把struct關鍵字定義的struct直接增強為一種數(shù)據(jù)類型柒啤;

另外還加強的一點是,struct和class一樣畸颅,可以對自己的元素設定訪問權限:public, protected, private担巩。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Teacher
{
    char name[64];
    int age;
};



struct Student
{
    char name[64];
    int id;
};

// advTeacher展示了增強的struct和class的相似性,區(qū)別以后再表
struct advTecher
{
public:
    char name[64];
    int  id;

protected:
    int class;

private:
    char age;
    
};

int main()
{
    Teacher t1;         //編譯器通過
    Student s1;         //編譯器報錯
    struct Teacher s1;  //這樣編譯器才通過
}

6. 三目運算符增強

在C語言中没炒,運算符的結果本質上就是一個數(shù)值涛癌,它不是變量,運算符表達式的結果直接保存在寄存器中送火。如果程序員試圖把它當做左值來賦值操作拳话,編譯器會報錯碍现;
C++中運算符的結果本質上被增強成為一個變量抗斤,它保存在內存中瞎疼,是可以當做左值被修改數(shù)值的传轰。

那么這是如何從C語言增強的?
其實就是C++的設計者們改變了運算符的返回對象措译,把C語言中只是返回一個數(shù)值改變?yōu)槁鸷疲祷匾粋€變量的地址揩页,代碼如下所示:

int a = 10, b = 20;

(a < b ? a : b)
// 改為
(a < b ? &a : &b)

這樣一來猖败,盡管運算符返回的仍然是一個數(shù)值速缆,但是這個數(shù)值是一個內存地址,我們想把它當做左值來進行賦值操作恩闻,只需要在地址的前面加上*取地址符即可艺糜。

*(a < b ? &a : &b) = 50;

這句話在C語言里面也是可以通過編譯并且能夠成功執(zhí)行的。C++的增強實質就是C++編譯器幫助程序員們完成了這個操作判呕。
而當運算符是右值的時候,就保持C語言中的處理方式送滞。

7. 對關鍵字const加強

為了盡可能搞清楚這個話題侠草,我把之前的C語言筆記直接搬回來:

辨析一下const修飾的位置:

const int a;
int const a;

上面這兩句話的作用是相同的。

const int *a;
int const *a;

這兩句話句話也是同樣的作用:指針指向地址的內容不能更改犁嗅,指針指向的地址可以更改边涕。

int *const a;

const修飾的是a:a指向的地址不可以更改,但是地址里面的內容可以更改。
總結了以下規(guī)律:

    1. 只看const后面的內容,const 后面是個a功蜓,a本身是一個指針變量园爷,所以就是指針的值不能改了;
    1. const后面是*a 或int *a,就是說*a不能改,即a指向的內存的內容不能更改式撼。
int main()
{
    const int a;    // 整型變量a的值不可修改
    int const b;    // 同上

    const char *c;  // 這樣的代碼按照“從右往左”的順序開始理解即可避免概念混淆
    char *const d;  // const char *c = const (char *c): char *c 指向的是一個存儲char類型的值的內存童社,
                    // 再用const修飾這個內存地址,意思就是:char *c 指向的內存地址不可以被更改著隆,
                    // 但是指針c可以指向其他的內存地址扰楼,指向了新的內存地址后,新的內存的內容也就不能更改美浦。
                    // 同理弦赖,char *const d = char (*const d): *d是一個指針變量(類型不明,指向不明浦辨,
                    // 但是已經(jīng)為d分配了內存空間)蹬竖。那么就是d的指向不能改變,d只能一直指向一個固定
                    // 的內存空間流酬,再用char 來修飾說明币厕,這個d指向的內存空間存儲char 類型的值,
                    // 這個內存空間存儲的值當然可以修改的 
    
    const char *const e;     // 同理康吵,const char *const e = {const [char *(const e)]}: 
                             // e的值不變劈榨,e是一個指針,指針e指向一個char類型變量晦嵌,
                             // 指針e指向的char變量是不能更改的同辣。
}

下面直接說這個話題的結論:
const關鍵字在C語言編譯器器中并不能真正起到鎖定變量值的作用,因為我們只要使用一個變量同類型的指針變量p惭载,用p即可直接修改變量的值旱函;*
但是在C++編譯器中真正做到了鎖定變量的值,同樣的代碼描滔,使用p來修改變量值棒妨,然后打印結果,發(fā)現(xiàn)變量的值不變含长。*

void main()
{
    const int a = 10;
    int *p = NULL;

    p = (int *)&a;
    *p = 9999;
    
    printf("a: %d \n", a);  
//  C語言編譯器處理后運行結果:a: 9999
//  C++編譯器處理后運行結果:a: 10
}

下面我們來把C++編譯器的工作解釋一下:
在使用了const關鍵字修飾變量后券腔,C++編譯器會把變量存放在“符號表”中,符號表里面存儲的都是鍵值對:key-value拘泞。
注意:這里的“符號表”是和之前的“內存四區(qū)”是兩個概念纷纫,不要拿來試圖相互說明。
但是在代碼

p = (int *)&a;

中執(zhí)行的是什么操作呢陪腌?編譯器會再分配一個新的空間來存放當前a的值辱魁,所以p獲取的內存地址和a并沒有關系烟瞧,所以C++編譯器把const修飾的變量真正變成了一個常量。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末染簇,一起剝皮案震驚了整個濱河市参滴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌锻弓,老刑警劉巖砾赔,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異弥咪,居然都是意外死亡过蹂,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門聚至,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酷勺,“玉大人,你說我怎么就攤上這事扳躬〈嗨撸” “怎么了?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵贷币,是天一觀的道長击胜。 經(jīng)常有香客問我,道長役纹,這世上最難降的妖魔是什么偶摔? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮促脉,結果婚禮上辰斋,老公的妹妹穿的比我還像新娘。我一直安慰自己瘸味,他們只是感情好宫仗,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著旁仿,像睡著了一般藕夫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上枯冈,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天毅贮,我揣著相機與錄音,去河邊找鬼尘奏。 笑死滩褥,一個胖子當著我的面吹牛,可吹牛的內容都是我干的罪既。 我是一名探鬼主播铸题,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼琢感!你這毒婦竟也來了丢间?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤驹针,失蹤者是張志新(化名)和其女友劉穎烘挫,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體柬甥,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡饮六,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了苛蒲。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片卤橄。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖臂外,靈堂內的尸體忽然破棺而出窟扑,到底是詐尸還是另有隱情,我是刑警寧澤漏健,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布嚎货,位于F島的核電站,受9級特大地震影響蔫浆,放射性物質發(fā)生泄漏殖属。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一瓦盛、第九天 我趴在偏房一處隱蔽的房頂上張望洗显。 院中可真熱鬧,春花似錦谭溉、人聲如沸墙懂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽损搬。三九已至,卻和暖如春柜与,著一層夾襖步出監(jiān)牢的瞬間巧勤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工弄匕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留颅悉,地道東北人。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓迁匠,卻偏偏與公主長得像剩瓶,于是被迫代替她去往敵國和親驹溃。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內容

  • C++入門基礎 namespace專題講座 namespace概念 所謂namespace延曙,是指標識符的各種可見范...
    蔡俊宇閱讀 792評論 0 2
  • 一豌鹤、 為什么需要命名空間(問題提出) 命名空間是ANSIC++引入的可以由用戶命名的作用域,用來處理程序中 常見的...
    IvanRunning閱讀 2,364評論 0 2
  • 重新系統(tǒng)學習下C++枝缔;但是還是少了好多知識點布疙;socket;unix愿卸;stl灵临;boost等; C++ 教程 | 菜...
    kakukeme閱讀 19,940評論 0 50
  • 第一章 計算機與C++編程簡介 C++程序6個階段編程 ->預處理->編譯->連接->裝入->執(zhí)行1.程序在編譯器...
    rogertan30閱讀 3,869評論 0 1
  • 我的朋友小英姐氣鼓鼓地從店門口走過來趴荸,把裝手機的小包包往茶桌上一摔儒溉,大巴鬼大巴鬼地說開了…… 她罵人大巴鬼就是...
    狂小烹閱讀 2,414評論 47 34