一:背景
最近發現 C++ 中的類型初始化操作,沒有 {}
運算符搞不定的,蠻有意思,今天我們就來逐一列一下各自的用法以及匯編展現,本來想分為 值類型
和 引用類型
兩大塊,但發現在 C++ 中沒這種說法,默認都是 值類型
😂😂😂
二:各種玩法一覽
1. int 上的初始化
首先看一下代碼:
int?main()
{int?i?=?{?10?};int?j{?10?};printf("i=%d,?j=%d",?i,?j);
}
相比C#來說,不帶 =
的寫法感覺還是怪怪的。。。接下來看下對應的匯編代碼。
int?i?=?{?10?};
00021825??mov?????????dword?ptr?[ebp-8],0Ah??int?j{?10?};
0002182C??mov?????????dword?ptr?[ebp-14h],0Ah
從匯編代碼看,就是一個簡單的 棧賦值
,所以在 int 上用 {}
完全沒必要,太傷鍵盤了。
2. 數組的初始化
繼續看例子。
int?main()
{int?num[]?=?{?10,11,12?};
}
這種寫法中規中矩,基本上 C 系列的語言都這樣,對于玩 C# 的我來說,不陌生。。。不過人家默認是值類型,C# 是引用類型,從匯編代碼中也能看的出來。
int?num[]?=?{?10,11,12?};
009C1E95??mov?????????dword?ptr?[ebp-10h],0Ah??
009C1E9C??mov?????????dword?ptr?[ebp-0Ch],0Bh??
009C1EA3??mov?????????dword?ptr?[ebp-8],0Ch
3. 結構體的初始化
結構體大家都很熟悉,直接上代碼了。
typedef?struct?_Point
{int?x;int?y;
}?Point;int?main()
{Point?point?=?{?10,20?};
}
接下來看一下匯編代碼。
Point?point?=?{?10,20?};
00481825??mov?????????dword?ptr?[ebp-0Ch],0Ah??
0048182C??mov?????????dword?ptr?[ebp-8],14h
可以看到,其實也是一組簡單的賦值操作,很方便。
4. 類的初始化
方便講述,先上代碼:
class?Location?{
private:int?x;int?y;int?z;
public:Location(int?x,?int?y,?int?z)?:x(x),?y(y),?z(z)?{}
};int?main()
{Location?location?=?{?10,11,12?};
}
接下來看下匯編代碼,是不是調用了 Location 的構造函數。
Location?location?=?{?10,11,12?};
008D183F??push????????0Ch??
008D1841??push????????0Bh??
008D1843??push????????0Ah??
008D1845??lea?????????ecx,[ebp-14h]??
008D1848??call????????Location::Location?(08D13A7h)
可以看到確實調用了 構造函數,那個 ecx 就是 location 的 this 指針。
5. initializer_list 模板類
C++ 中的 initializer_list 類可以接收 {}
初始化語法作為初始化操作,這個有一點像 C# 的 param
可選參數,接下來把上例的中構造函數改成 initializer_list
來接收,代碼如下:
class?Location?{
public:int?x;int?y;int?z;
public:Location(initializer_list<int>?list)?{x?=?*(const_cast<int*>(list.begin()));y?=?*(const_cast<int*>(list.begin()?+?1));z?=?*(const_cast<int*>(list.begin()?+?2));}
};int?main()
{Location?loc?=?{?10,11,12?};printf("loc.x=%d,loc.y=%d,loc.z=%d",?loc.x,?loc.y,?loc.z);
}
接下來看下匯編代碼。
Location?loc?=?{?10,11,12?};
00B9518F??mov?????????dword?ptr?[ebp-0F8h],0Ah??
00B95199??mov?????????dword?ptr?[ebp-0F4h],0Bh??
00B951A3??mov?????????dword?ptr?[ebp-0F0h],0Ch??
00B951AD??lea?????????eax,[ebp-0ECh]??
00B951B3??push????????eax??
00B951B4??lea?????????ecx,[ebp-0F8h]??
00B951BA??push????????ecx??
00B951BB??lea?????????ecx,[ebp-0E4h]??
00B951C1??call????????std::initializer_list<int>::initializer_list<int>?(0B913C5h)??
00B951C6??mov?????????edx,dword?ptr?[eax+4]??
00B951C9??push????????edx??
00B951CA??mov?????????eax,dword?ptr?[eax]??
00B951CC??push????????eax??
00B951CD??lea?????????ecx,[loc]??
00B951D0??call????????Location::Location?(0B913ACh)
從匯編代碼看,它首先做了 initializer_list
的初始化操作,然后將弄好的集合丟到 Location
構造函數中,反轉過來大概就是這樣。
int?main()
{initializer_list<int>?list?=?{?10,11,12?};Location?loc?=?{?list?};printf("output:?loc.x=%d,loc.y=%d,loc.z=%d",?loc.x,?loc.y,?loc.z);
}
哈哈,是不是感覺 {}
在初始化方面無所不能,好了,本篇就聊到這里了。