当前位置: 首页 > news >正文

C++ Attribute 属性说明符

目录

  • 属性说明符 Attribute
    • 编译警告相关
      • [[deprecated]]
      • [[maybe_unused]]
      • [[fallthrough]]
      • [[nodiscard]]
    • 可能触发编译优化
      • [[noreturn]]
      • [[likely]]、[[unlikely]]
      • [[assume]]
      • [[carries_dependency]]
      • [[no_unique_address]]

属性说明符 Attribute

属性说明符Attribute自C++11起,允许程序员给编译器提供额外的信息让其对程序进行优化、检查、约束。

它并不是新东西,各家编译器本来就有自带的各种属性,标准属性把一些经典的属性给标准化了

编译警告相关

这类属性和编译期警告有关,不会影响最终编译出的程序。

  • 可以打开和关闭

  • 最为常用,且不容易出错的属性。

[[deprecated]]

指示声明有此属性的名字或实体被弃用,即允许但因故不鼓励使用。实体包括类型(struct,class,union)、别名、变量、非静态数据成员、函数、命名空间,枚举类型、枚举类型中的一项、模版特化这些实体。

使用案例:

[[deprecated("Please use int foo2()")]]int foo() { return 2;}

如果调用foo函数,编译器就会报警告:

<source>:9:15: warning: 'int foo()' is deprecated: Please use int foo2() [-Wdeprecated-declarations]9 |     return foo();|            ~~~^~

[[maybe_unused]]

抑制对未使用实体的警告。

实体包括类型(struct,class,union)、别名、变量、非静态数据成员、函数、命名空间,枚举类型、枚举类型、结构化绑定。

典型的场景是关闭一些因为log级别变化而产生未使用变量编译警告:

#ifdef ENABLE_DEBUG_LOG
#define LOG_DEBUG(x)  {  std::cout <<"D: " << x <<"\n";}
#else
#define LOG_DEBUG(x) // nothing
#endifint foo() {[[maybe_unused]]const char* errorMessage="Wrong";// 生产环境中debug级别的日志不会被打印,所以errorMessage实际上是不会被使用的LOG_DEBUG(errorMessage)return 0;
}

[[fallthrough]]

指示switch语句中从前一标号直落是有意的,而在发生直落时给出警告的编译器不应诊断它。

void f(int n)
{int local{0};switch (n){case 1:case 2:local += 1;[[fallthrough]];case 3: // 直落时不警告local *= 2;case 4:while (false){[[fallthrough]]; // 非良构:下一语句不是同一迭代的一部分}case 6:[[fallthrough]]; // 非良构:没有后继的 case 或 default 标号}
}

[[nodiscard]]

可被用于函数声明、类声明、枚举类型声明中。

不是 void 的 弃值表达式(discarded-value expression)(即非返回值未被接收的表达式)中,则鼓励编译器发布警告。

调用声明为 nodiscard 的函数,或

调用按值返回声明为 nodiscard 的枚举或类的函数,或

以显式类型转换或 static_cast 形式调用声明为 nodiscard 的构造函数,或

以显式类型转换或 static_cast 形式构造声明为 nodiscard 的枚举或类的对象,

它有好几个使用场景:

  • 迫使程序员检查错误码,如下:
enum class[[nodiscard]] ErrorCode {Success,Wrong
};// 当调用该函数却没有检查其返回值时,会报编译警告
ErrorCode foo() {return ErrorCode::Success;
}
  • 警告资源泄露,比如程序员分配了内存却不使用它,这会造成资源泄露。

    因此operator newnodiscard 的属性。

另一个使用场景是警告调用错误,比如在对C++容器不熟悉的程序员很容易将容器的成员函数empty()认为是清空容器,因此几乎所有容器的empty() 成员函数都有nodiscard属性,一旦发生调用该函数却不检查返回值,大概率是empty()被错误使用了。

可能触发编译优化

这类属性可能触发编译优化,这些优化会影响最终编译出来的程序。这些属性可能会引发程序错误,谨慎使用。

[[noreturn]]

编译器会根据这个属性对程序进行优化,比如会直接忽略在该函数之后的代码。

  • 告诉编译期函数不会返回,直接终止程序。
  • 如果该函数返回,那么程序行为未定义。

[[likely]]、[[unlikely]]

允许编译器为包含该语句的执行路径,比任何其他不包含该语句的执行路径,更可能或更不可能的情况进行优化。

  • 可用于if语句
  • 可用于switch语句

编译器可能会根据该属性更改代码布局,比如对instruction cache更加友好。它不会影响芯片的分支预测功能,貌似没有指令可以指导分支预测电路。

[[assume]]

指示表达式在给定的位置永远会求值为true,编译器会根据该属性进行编译优化。

假设在不成立时会导致未定义行为,所以不建议使用。

[[carries_dependency]]

用来传递std::memory_order中release-consume的依赖链进入函数,这允许编译器跳过不必要的内存栅栏指令。

不推荐使用,甚至有专门的P0371R1: Temporarily discourage memory_order_consume用来传递std::memory_order中release-consume的依赖链进入函数,这允许编译器跳过不必要的内存栅栏指令。不推荐使用paper。

[[no_unique_address]]

允许此数据成员与其类的其他非静态数据成员或基类子对象重叠。

可以用来优化空类成员变量,编译器可将它优化为不占空间,就像空基类优化一样。

struct Empty {};
// 使用空基类优化
struct EmptyBaseOptimization: public Empty {int i;
};
struct Foo_noOpt {Empty empty;int i;
};
// 使用[[no_unique_address]]
struct Foo_Opt {[[no_unique_address]] Empty empty;int i;
};int main() {// 空类也是有大小的static_assert(sizeof(Empty) == 1);// 空基类优化会使得空基类不占用空间static_assert(sizeof(EmptyBaseOptimization) == 4);// 空类的成员也会占用内存空间,为了对齐,占据四个字节static_assert(sizeof(Foo_noOpt) == 8);// Foo_Opt对空类成员使用了[[no_unique_address]]属性,它被优化掉了static_assert(sizeof(Foo_Opt) == 4);
}

http://www.mrgr.cn/news/89975.html

相关文章:

  • 【正点原子K210连载】第六十七章 音频FFT实验 摘自【正点原子】DNK210使用指南-CanMV版指南
  • C#常用744单词
  • wordpressAI工具,已接入Deepseek 支持自动生成文章、生成图片、生成长尾关键词、前端AI窗口互动、批量采集等
  • 探讨如何在AS上构建webrtc(2)从sdk/android/Build.gn开始
  • #渗透测试#批量漏洞挖掘#微商城系统 goods SQL注入漏洞
  • 网盘资源查找工具---AI功能
  • 人工智能图像分割之Mask2former源码解读
  • C语言练习题
  • burpsuite抓取html登陆和上传数据包
  • open3d将numpy数组可视化
  • 本地部署DeepSeek + Ragflow
  • python - 封装moondream(备份)
  • redis项目
  • git学习
  • 【LeetCode 刷题】动态规划(1)-基础
  • 组合(力扣77)
  • Ollama下载安装教程
  • Unity Dots学习
  • 【0404】Postgres内核 实现分配一个新的 Object ID (OID)
  • gitlab多项目流水线
  • C++Primer学习(2.2)
  • 【LeetCode 刷题】贪心算法(4)-区间问题
  • ubuntu20.04+RTX4060Ti大模型环境安装
  • 【机器学习】超参数的选择,以kNN算法为例
  • 学习数据结构(6)单链表OJ上
  • redis之GEO 模块