文章目录

  • 1.编译器扩展属性
  • 2.C++11通用属性
    • 2.1语法格式
    • 2.2[[ noreturn ]]
    • 2.3[[carries_dependency]]
  • 3.C++14与C++17通用属性
  • 参考文献

1.编译器扩展属性

C++在不断的发展,但每一阶段的C++标准提供的功能都很难完全满足现实需求,于是为了弥补标准的不足或者扩增特性应用场景所需的特性,各大C++编译器厂商多多少少在标准之外都增加了不少有用的扩展功能。这些扩展功能并不在C++的标准中,但是却经常被使用。有时候,C++标准委员会也会考虑这些标准之外的扩增特性,将其纳入标准之中。

C++扩增特性中较为常见的就是“属性”(attribute)。属性是对语言中实体对象(比如函数、变量、类型等)附加说明,用来实现一些语言及非语言层面的功能,或是帮助编译器优化代码。不同编译器有不同的属性语法,比如对于GCC ,属性是通过关键字__attribute__来声明的,常见的有format、noreturn、const和aligned等,申明语法如下:

__attribute__ ((attribute-list))

例如:

extern int area(int n) __attribute__ ((const))int main()
{int areas=0;for(int i=0;i<10;++i){areas+=area(3)+i;}
}

程序中const属性告诉编译器,该函数返回值只依赖于输入,不会改变函数外的数据,因此编译器可以对area(3)进行优化处理,只对函数调用一次,后续将area(3)视为常量进行操作,将大大提醒程序性能。

Windows平台VC++则使用__declspec来申明扩展属性,使用语法如下:

__declspec (extended-decl-modifier)

比如控制类型对齐方式:

__declspec (align(32)) struct Struct32
{char c;int i;
}

其作用是类型Struct32定义的变量的起始地址是32的整数倍,且类型大小sizeof(Struct32)=32也是32的整数倍。

2.C++11通用属性

2.1语法格式

自C++11开始,C++拥有统一形式的通用属性申明方式,语法格式如下:

[[attribute-list]]

语法上,C++11通用属性可以作用于函数、类型、变量、代码块等,书写位置可以位于目标之前,也可以位于目标之后。对于作用于整个语句的通用属性,则应该写在语句起始处。如果出现在以上两种位置之外的通用属性,作用于哪个实体跟编译器具体实现有关。例如:

//作用于函数
[[ attr1 ]] void func();
//或者
void func [[ attr2 ]] ();//作用于数组
[[ attr1 ]] int array[10];
//或者
int array [[ attr1 ]] [10];

C++11只定义了两种通用属性,分别是[[ noreturn ]]与[[ carries_dependency ]],其它如[[ final ]]、[[ override ]]、[[ restrict ]]、[[ hides ]]、[[ base_check ]]等属性,考虑到通用性和实现方式,未纳入标准,比如final、override、restrict等为语言特性,通过关键字来实现。

2.2[[ noreturn ]]

[[ noreturn ]]用于标识不会返回的函数。不会返回的函数指的是被调处后面的代码不会执行,被调函数不会将控制流返回给主调函数,注意不是没有返回值的函数。通过这个属性,开发者可以告诉编译器进行代码优化,诸如死代码告警与消除等。参考如下示例:

void cout1() { cout << "cout1" << endl; }
void cout2() { cout << "cout2" << endl; }[[noreturn]] void throwAway()
{throw "exception";
}void foo()
{cout1();throwAway();cout2();       //该函数不可达
}

上面的代码中,cout2()不可达,编译器可以采用告警的方式提示开发者或者直接不生成调用cout2()的代码进行优化。

除了抛出异常可能会导致程序控制流不能返回调用者外,其它诸如包含终止应用程序或者无限循环语句的函数,都可以使用[[noreturn]]进行申明,比如C++11标准库中,我们可以看到如下函数申明语句:

[[noreturn]] void abort(void) noexcept;

当然,[[noreturn]]可以帮助编译器进行代码优化,前提是正确使用。如果错误地使用[[noreturn]]可能会给程序带来致命损害,因此要小心翼翼。

2.3[[carries_dependency]]

[[ carries_dependency ]]作用于函数参数与返回值,用于避免在弱一致性模型平台上产生不必要的内存栅栏,降低代码效率。比如:

atomic<int*> a;
...
int* p=(int*)a.load(memory_order_consume);
func(p);

由于编译器在编译到func时不知道func中的具体实现,因为使用了原子变量a对p赋值时使用了memory_order_consume内存顺序模型,所以需要保证a.reload先于任何关于a(或者p)的操作,编译器往往会在func函数之前加入一条内存栅栏。然而如果func的实现是:

void func(int* p)
{...//假设p2是一个atomic<int*>的变量p2.store(p,memory_order_release);
}

那么对于func函数来说,由于使用memory_order_release的内存顺序,p2.store对p的使用会被保证在任何关于p的操作之后进行。这样一来,编译器在func函数之前加入内存栅栏毫无意义,并影响了性能,解决办法是对函数参数使用[[ carries_dependency ]]属性:

void func(int* [[ carries_dependency ]] p);

同样的,[[ carries_dependency ]]也可以用于返回值,语法格式如下:

[[ carries_dependency ]] int* func();

事实上,对于强内存模型平台来说,如x86-64,编译器往往会忽略该属性,因此该属性使用比较有限。如果开发平台是弱类型模型,并且很关心并行程序的执行性能时,可以考虑使用[[ carries_dependency ]]。

3.C++14与C++17通用属性

在C++11的基础上,C++新标准C++14与C++17对通用属性进行了补充,主要有:

(1)[[deprecated]]与[[deprecated(“reason”)]]
标准:C++14;
作用:指示允许使用声明有此属性的名称或实体,但因指定的reason,不鼓励使用;
示例:class [[deprecated]] Outdate{};

(2)[[fallthrough]]
标准:C++17;
作用:出现在switch语句中,抑制上一句case没有break而引起的fallthrough的警告;
示例:

switch(i)
{case 1: something();[[fallthrough]];case 2:something();[[fallthrough]];default:break;
}

(3)[[nodiscard]]
标准:C++17;
作用:若返回值被舍弃,则鼓励编译器发出警告。
示例:

[[nodiscard]] int something()
{return 1;
}

(4)[[maybe_unused]]
标准:C++17;
作用:抑制编译器在未使用实体上发出警告。
示例:

 [[maybe_unused]] int a = something();

使用以上通用属性,可以帮助我们更好的优化和管理代码。C++20已经在路上,新标准会继续在通用属性方面作出更多的扩增。


参考文献

[1]深入理解C++11[M].8.2通用属性
[2]《深入理解C++11》笔记-对齐支持和通用属性
[3]attribute specifier sequence(since C++11)
[4]C++的属性指示符

C++0x 通用属性相关推荐

  1. OpenCASCADE绘制测试线束:OCAF 命令之通用属性命令

    OpenCASCADE绘制测试线束:OCAF 命令之通用属性命令 通用属性命令 SetInteger GetInteger SetReal GetReal SetIntArray GetIntArra ...

  2. 【安卓开发 】Android初级开发(一)控件通用属性

    控件通用属性 match_parent 是指和父容器宽高相等的值,其他的同理可证. android:layout_marginTop="XXXXXXdp" 距离顶部的距离 Andr ...

  3. Python之数据分析(Numpy通用属性、数据可视化与matplotlib库通用函数)

    文章目录 一.ndarray属性 二.数据可视化 一.ndarray属性 1.通用属性 dtype:数组类型 shape:数组维度 T:转置视图 ndim:维数(一维是1,二维是2,三维是3--) s ...

  4. 获取一些系统和用户的通用属性

    1. 在ASP.NET中专用属性: 获取服务器电脑名:Page.Server.ManchineName 获取用户信息:Page.User 获取客户端电脑名:Page.Request.UserHostN ...

  5. 07-HTML通用属性

    HTML通用属性 HTML5保留的通用属性 id.style.class属性 dir属性 title属性 lang属性 accesskey属性 tabindex属性 HTML5新增的通用属性 cont ...

  6. 2019FME博客大赛——基于FME的地理国情监测 变化信息通用属性项检查

    参赛单元:传统GIS数据处理 作者:陈兴波 单位:宁夏回族自治区基础测绘院 1 绪论 1.1 背景 基础性地理国情监测引入的变化信息通用属性项,通过人机交互检查容易出现错漏,且速度慢,因此需要设计对应 ...

  7. WPF---->通用属性表,TextBox,TextBox字体设置,Border

    文章目录 通用 通用属性列表 TextBox TextBox属性目录 TextBox字体的设置 TextBox选中指定文本 Border 属性表 外阴影 通用 通用属性列表 属性 作用 值 示例 图示 ...

  8. OpenHarmony/HarmonyOS文本通用属性

    文本通用属性 作者:坚果 团队:坚果组织 公众号:"大前端之旅" 润开鸿技术专家,华为HDE,InfoQ签约作者,OpenHarmony布道师,擅长HarmonyOS应用开发.熟悉 ...

  9. javabean链式调用优雅通用属性赋值法

    [问题]如何使用类的同一个方法给该类的属性赋值(例如val方法)? 1.首先定义一个实现Serializable的函数式接口 @FunctionalInterface public interface ...

最新文章

  1. 将文件上传至ftp服务器,FTP文件上传工具类,将文件上传至服务器指定目录
  2. Lesson 16.5 在Pytorch中实现卷积网络(上):卷积核、输入通道与特征图在PyTorch中实现卷积网络(中):步长与填充
  3. 数组中的元素赋值给元素_漫画:寻找无序数组的第k大元素
  4. FreeTextBox1.6版本控件使用总结(未完)
  5. C#程序只允许运行一个实例的解决方案
  6. caffe模型文件解析_Caffe ImageData神经网络基本示例无法解析模型文件
  7. 多条实体类数据怎么接受_解决并发问题,数据库常用的两把锁!
  8. Oracle的distinct关键字
  9. 加载项找不到java,未显示自定义Outlook加载项
  10. awk编程之数组、控制流(长期更新)
  11. 彻底搞懂遗传算法原理+代码讲解+具体例子
  12. 解决Adobe PhotoShop用户界面字体过小的问题
  13. Pillow图像几何变换
  14. 【源码】FOMCON version 1.22.0.0——基于分数阶微积分的系统建模和控制设计工具箱
  15. ZZNU 2125:A + B 普拉斯(傻逼题+大数加法)
  16. 微信小程序原生开发功能合集一:微信小程序开发介绍
  17. 嘉洋独家观点:关于近期股市的详解
  18. 2023海南大学计算机考研信息汇总
  19. 双目视觉测量系统在不同纵向距离中测量精度比对实验
  20. 408-数据结构-树的应用-哈夫曼树并查集

热门文章

  1. [数位DP]JZOJ 3363 Number
  2. iOS tableview嵌套collectionview
  3. linux下挂载U盘的方法
  4. 使用Python实现生产者消费者问题
  5. tcpip数据包编码解析(chunk and gzip)_space of Jialy_百度空间
  6. 实业逻辑与品牌逻辑的矛盾
  7. 安装CentOS的注意事项
  8. L1-065 嫑废话上代码 (5 分)-PAT 团体程序设计天梯赛 GPLT
  9. 蓝桥杯 PREV-32 历届试题 分糖果
  10. erlang rebar 配置mysql_Centos6.4安装erlang并配置mysql数据库