C++11开始支持属性attribute机制,可以使用属性进行一些格外描述,让编译器进行不同的操作。
如下是当前支持的标准属性,这些属性都可以通过宏**__has_cpp_attribute(属性记号)**判断编译器是否支持:
| 属性记号 | 属性使用格式 | 标准 | 作用 |
|---|---|---|---|
| carries_dependency | [[carries_dependency]] | (C++11) | 允许编译器跳过不必要的内存栅栏指令 |
| deprecated | [[deprecated]] | (C++14) | 表示该元素被弃用,编译器会给一个告警 |
| fallthrough | [[fallthrough]] | (C++17) | 用以switch case,表示故意在case结尾不加break |
| maybe_unused | [[maybe_unused]] | (C++17) | 关闭编译器提示参数或变量未使用的告警 |
| no_unique_address | [[no_unique_address]] | (C++20) | 表示struct中某成员拥有空类型特征 |
| nodiscard | [[nodiscard]] | (C++17) | 用于函数返回值前,该函数返回值必须被使用或处理,否则提示warning |
| [[nodiscard(“string”)]] | (C++20) | C++20增强,可以自定义warning内容 | |
| noreturn | [[noreturn]] | (C++11) | 用于函数前面,表示该函数不会再返回调用端。比如在函数内直接结束进程 |
| unlikely | [[unlikely]] | (C++20) | 用于if判断后或switch case前面,表示某个分支的可能性大小,用于帮助编译器优化代码 |
| likely | [[likely]] | (C++20) |
特别说一下no_unique_address,比较复杂,有以下特性:
①同类型的子对象或成员不占用同一个地址;
②当地址不够分配时,则按照一般做法扩展空间,继续为未分配地址的no_unique_address属性成员分配地址,直至全部分配完毕;
③该属性对空类型(没有非静态数据成员)有效。
使用示例:
//C++ attributes使用示例#include <iostream>using namespace std;//使用nodiscard属性,返回值必须被处理使用[[nodiscard("barret")]] int func1(){return 1;}//使用maybe_unused属性,关闭未使用的告警int func2(int a, [[maybe_unused]] int b){return 2;}//noreturn属性,表示函数调用栈不会返回[[noreturn]] void forceExitProgram(){std::exit(1); //结束进程}bool isIdLicensed(int id){if (true)forceExitProgram();elsereturn true;}//deprecated属性,表示该C++元素被弃用[[deprecated]] int func3(){return 3;}//no_uniquire_address属性struct A{ }; // 空类型struct B{long long v;[[no_unique_address]] A a, b;};int main(){// func1(); //编译告警// forceExitProgram();// func2(1, 2);// // bool isLicensed{isIdLicensed(42)};// cout << func3() << endl;// int input = 0;// cout << "input a value:";// cin >> input;// switch (input)// {// [[unlikely]] case 0 : //表示该分支发生可能性很小// cout << "i am 0"<<endl;// break;// [[likely]] case 1: //表示该分支很可能发生// cout << "i am 1"<<endl;// [[fallthrough]] //故意不加break;// default:// cout << "i am not 0"<<endl;// break;// }//使用struct BB b;std::cout << &b.v << std::endl; // 输出v地址std::cout << &b.a << std::endl; // a地址为 &v + 1std::cout << &b.b << std::endl; // b地址为 &v + 2std::cout << sizeof(B) << std::endl; // 输出 16}
