![](/style/images/good.png)
![](/style/images/bad.png)
聊聊 C++ 大一统的初始化运算符 {}
source link: https://www.cnblogs.com/huangxincheng/p/16465318.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
最近发现 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);
}
哈哈,是不是感觉 {}
在初始化方面无所不能,好了,本篇就聊到这里了。
![图片名称](https://images.cnblogs.com/cnblogs_com/huangxincheng/345039/o_210929020104%E6%9C%80%E6%96%B0%E6%B6%88%E6%81%AF%E4%BC%98%E6%83%A0%E4%BF%83%E9%94%80%E5%85%AC%E4%BC%97%E5%8F%B7%E5%85%B3%E6%B3%A8%E4%BA%8C%E7%BB%B4%E7%A0%81.jpg)
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK