文中例程是本人自己理解和看网页的例子整理出来的,如有错误麻烦及时指正,水平有限,望与各位多多交流
这一节是对函数的声明和定义给一个总的概括的
原文地址:http://zh.cppreference.com/w/cpp/language/attributes
http://zh.cppreference.com/w/cpp/language/alignas
以下是注解和例程内容
属性
首先是属性,属性是实现了对语言的扩展,并且结合声明(总篇,声明地址)可以发现,属性几乎可以出现在任何地方,包括,指定符内,声明器内,所以这里又牵扯出了声明的一个小重点(对于一个属性出现在指定符内则表明这个属性是应用到类型上的,出现在声明器内则表明应用到当前这个对象上)
说一说属性的语法,属性语法很简单
[[ attribute-list ]] //其中list由多个逗号分隔的attr表示
[[ using attribute-namespace : attribute-list ]] //using指定
identifier //合法的属性名字
attribute-namespace :: identifier //带了名称空间
identifier ( argument-list ) //有参数的属性
attribute-namespace :: identifier ( argument-list ) //带了名称空间的有参数的属性
这里要说的是如果用到了using的话,在当前的属性列表内,不能再用相同的namespace用于attribute-namespace :: identifier类型的属性上。
考虑一下例子:
void f() {
int y[3];
y[[] { return 0; }()] = 1; // 错误
int i [[cats::meow([[]])]]; // OK
}
其中第一个是错误的,因为一个属性的检测,是通过[[ 来判断的,明显[[里的内容不是一个属性
再看第二个,i是一个变量,这个属性是作用于i对象(变量本身的)
证明以上论点:考虑例子:
int ss()[[deprecated("reason")]]{return 1; } //Error
int ss[[deprecated("reason")]](){return 1; } //OK
int main()
{
int i[[deprecated("reason")]]; //OK
i = ss();
return 0;
}
但是要注意,对于声明有规则:
属性 指示符 声明器序列
这个情况下,属性是表示当前声明器的内容
考虑例程:
[[deprecated("reason")]] int ss(){return 1; }//OK
int main()
{
[[deprecated("reason")]] int i;//OK
i = ss();
return 0;
}
alignas
这个是强行对齐的一个标识
对齐这里很简单,具体对齐介绍方法就不提了
但是要注意,对于一个非法的对齐的情况和形态,如果一个类的对齐大于类限定的对齐(并且这个数不为0)则这个对齐就是病态的,考虑:
struct alignas(8) S {};
struct alignas(1) U { S s; }; // 错误:若无 alignas(1) 则 U 的对齐将为 8