1. 程式人生 > >[技術]淺談初始化語義與賦值語義

[技術]淺談初始化語義與賦值語義

真的 class 基本 復制構造函數 spa 數值 復制構造 得到 對數

背景

博主是一個常年使用初始化語義的coder= =,所以經常會遇到這樣的對話

int tmp(0);

XXX:誒,你這tmp函數是幹什麽的啊

博主:蛤?我哪裏定義了tmp函數了

XXX:那你這個是什麽啊

博主:初始化啊,跟你打這個鬼東西是一樣的啊

int tmp=0;

XXX:蛤蛤蛤?

然後兩人都陷入了茫然狀態= =

基本介紹

觀察這兩行代碼

string tmp1("2333");
string tmp2="666";

有什麽區別呢(不要說一個打的醜,一個打的優美)

顯然,根據剛才的對話,第一行是初始化語義,第二行是賦值語義

首先,引一下度娘:

初始化在計算機編程領域中指為數據對象或變量賦初值的做法,如何初始化則取決於所用的程序語言以及所要初始化的對象的存儲類型等屬性。用於進行初始化的程序結構則稱為初始化器或初始化列表。初始化和變量聲明是有明顯區別的,而且初始化也先於變量聲明進行,但兩者在實踐中仍常被混淆。

將某一數值賦給某個變量的過程,稱為賦值。

也就是說,在第一行的代碼中,我們在聲明變量的時候,已經在初始化列表中為其初始化了一個值(比如tmp1,它在聲明時就已經是"2333"了),但在第二行的代碼中,我們已經聲明了變量,申請了內存,有了一個初始化的值(這決定於你聲明該變量的位置,是在堆裏還是在棧裏),然後,你再用"666"給tmp2賦值

這個區別就很顯然了

使用

繼續看代碼

struct a{
    int data,id;
    a(int d=0,int i=0):data(d),id(i){}
};

看a的定義,我們提供了一個構造函數a::a(),當我們這樣定義一個結構a的變量時,我們得到了一個data和id都為0的變量tmp

a tmp;

我們自然也可以給它賦上值,比如:

int data(2333),id(666);
a tmp(data,id);

這樣,我們就得到了一個data為2333,id為666的結構體變量tmp

但是,顯然我們有另一種寫法:

struct
a{ int data,id; a(int d=0,int i=0){ data=d,id=i; } };

這樣,我們再運行這段初始化代碼,得到的結果是一樣的

所以,我們為什麽要使用初始化語義呢?

為什麽使用初始化語義

這涉及到了兩種語義的開銷問題

我們在使用賦值語義時,在構造函數中,是對數據成員進行賦值,不是初始化,而數據成員會先調用默認構造函數,再調用賦值構造函數,(其實上例是不太恰當的,因為int是內置類型,如果使用一個類作為數據成員,比如string類,效果會更加明顯),這樣的開銷顯然要大一些。

而初始化語義則會調用復制構造函數(又稱為拷貝構造函數),開銷會小一些。

這樣,效率就會提升

(可能這對於OIer們沒啥用,但是在以後編寫工程時,會有一些大的類與對象,在這些對象上使用兩種語義,開銷的大小差距會變得明顯起來)

總結

其實兩種語義都是可以使用,並都能達到我們想要的效果的,但是在開銷方面,初始化語義顯然更勝一籌

(據說現在編譯器會自動優化賦值語義,不知道是不是真的= =)

總結完畢,希望對您有用

[技術]淺談初始化語義與賦值語義