

C++ 的指定初始化器
source link: https://blog.coderzh.com/2019/02/24/cpp-designated-initializers/?amp%3Butm_medium=referral
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.

C99 开始支持了指定初始化器(Designated Initializers),用来方便的初始化结构体或者数组数据。
比如下面的结构体:
typedef struct Rect { int x; int y; int width; int height; } Rect;
可以这样初始化:
Rect r = { .width = 100, .height = 100, };
其中 x, y 未指定的话,会自动初始化为 0。花括号里的字段顺序也没有要求。如果要初始化一个全是 0 的结构体,可以这样:
Rect r = {0}; // Or Rect r1 = {};
需要特别注意的是,第一种写法 {0}
,里的 0,并不是说每个字段都赋值成 0,而是说第一个字段赋值为 0,其余字段用默认值(刚好也是 0)。
假如我们写成:
Rect r = {1}; // r will be { 1, 0, 0, 0}, not {1, 1, 1, 1}
再来看看几个数组初始化的列子:
int a[8] = {[5] = 25, [2] = 15 }; // Or int a[8] = {[5]25 , [2]15 }; // Equals int a[8] = { 0, 0, 15, 0, 0, 25, 0, 0 };
甚至可以用 [first...last]=value
来指定一个区间的值:
int a[] = {[2 ... 3] = 2, [5] = 25}; // Equals int a[] = { 0, 0, 2, 2, 0, 25 }
注意 [first...last]
是从 first 到 last 的闭区间。
指定初始化甚至还可以嵌套,假如结构体定义是这样的:
typedef struct Point { int x; int y; } Point; typedef struct PointCloud { Point p[10]; int width; int height; } PointCloud;
可以这样初始化 PointCloud:
Rect r = { .p[0] = { .x= 10, .y= 10 }, .width = 100, .height = 100 };
然后,甚至可以写出像这样的代码:
void init_some(PointCloud* p) { // do some init } int main(int argc, char* argv[]) { init_some(&(PointCloud){ .p[0] = { .x = 10, .y = 10 }, .width = 100, .height = 100 }); // ... }
上面代码如果使用 C++ 编译,会报错: error: taking the address of a temporary object of type 'PointCloud' [-Waddress-of-temporary]
,可以加编译参数 -Wno-address-of-temporary 解决。不过不是很推荐这么做,关掉这个可能会带来其他隐藏的 BUG。
上面的代码看上去已经不像 C 了,像是另外一门语言。但是简化了初始化的过程。
好了,看上去非常酷,但前面的代码都是纯 C 的,那 C++ 支不支持指定初始化器呢?遗憾的是,直到 C++20 才开始支持指定初始化器(都什么年代了,别人家的 C,99 年就支持了)。
如果在 linux 上用 gcc C++11 去编译上面的代码,会报下面的错:
sorry, unimplemented: non-trivial designated initializers not supported
也别太难过,好消息是作为现代编译器的 clang
,早早的就通过扩展的方式实现了指定初始化器。所以,即使是 C++11,使用 clang 编译和跑上面的代码,也是没有问题的。(Windows 的 MSVC 大概是指望不上了)
回到移动平台,Android NDK 开发时,能不能使用这一特性呢?Android NDK r11 开始就建议大家从 GCC 切到 clang,而且从 NDK r13 开始,默认使用 clang 编译。所以,只要 NDK r13 及以上,都可以愉快的使用这一特性。
Recommend
-
151
ArrayList部分一共五篇文章了,并且引入了时间复杂度来分析,强烈建议大家一定要按顺序阅读,本文是第1篇。前些天的文章,反复的画图,不停的重复,就是想让大家理解,对象在内存中是什么样的。也是为今天的及以后的讲解打下基础。如果要说大家在写Java代码的时候...
-
142
相信对于大部分使用过VueJS的同学来说,vue-cli是他们非常熟悉的一个工具。借助vue-cli,我们通过非常简单的问答形式,方便地初始化一个vue工程,完全不需要担心繁复的webpack、eslint配置等等。 但是,仍然有许多同学没有搞清楚
-
101
Spring-Cloud-Gateway 源码解析 —— 网关初始化 ...
-
142
摘要: 原创出处 http://www.iocoder.cn/SkyWalking/agent-init/ 「芋道源码」欢迎转载,保留摘要,谢谢! 本文主要基于 SkyWalking 3.2.6 正式版 本文主要分享 SkyWalking Agent 启动初始化的过程。 ...
-
135
-
81
在上一篇中,我们分析了play的2种启动方式,这一篇,我们来看看Play类的初始化过程
-
64
摘要: 原创出处 http://www.iocoder.cn/Eureka/eureka-client-init-first/ 「芋道源码」欢迎转载,保留摘要,谢谢!本文主要基于 Eureka 1.8.X 版本1. 概述2. EurekaInstanceConfig2.1 类关系图2.
-
104
-
57
-
9
Java中使用HashMap时指定初始化容量性能一定会更好吗? | XINDOO
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK