Logo
Section 1 / 5

简介

[[nodiscard]] 属性是一种向编译器传达我们意图的方式。本节将详细介绍其用法。

导入

简介

[[nodiscard]] 属性是一种向编译器传达我们意图的方式。本节将详细介绍其用法。

C++17 引入了更多标准属性。通过使用这些额外的注解,你不仅可以使代码对其他开发者更易读,还能让编译器利用这些信息。

例如,编译器可能会针对潜在错误生成更多警告。

或者相反:当编译器识别出程序员的明确意图时(例如使用 [[maybe_unused]]),它甚至可以避免产生某些警告。

在本章中,你将学习如何使用一个特定属性——[[nodiscard]]——来提升代码的安全性。

[[nodiscard]] 属性已在属性章节中提及,但这里通过一个简单示例回顾其特性。

该属性用于标记函数的返回值:

1[[nodiscard]] int Compute();

当你调用此类函数却未保存返回结果时:

1void Foo() { 2 Compute(); 3}

你应该会收到如下(或类似)警告:

1warning: ignoring return value of 'int Compute()', declared with attribute nodiscard

我们还可以进一步,不仅标记返回值,而是标记整个类型:

1[[nodiscard]] struct SuperImportantType { }; 2SuperImportantType CalcSuperImportant(); 3SuperImportantType OtherFoo(); 4SuperImportantType Calculate();

每当调用返回 SuperImportantType 类型的函数时,你都会收到警告。

换句话说,你可以强制实现函数的代码契约,确保调用者不会忽略返回值。有时这种遗漏可能导致程序出现错误,因此使用 [[nodiscard]] 能显著提高代码安全性。

编译器会生成警告,但通常建议在构建代码时启用“将警告视为错误”的选项。在 MSVC 中使用 /WX,在 GCC 中使用 -Werror。错误会中断编译过程,迫使程序员采取行动并修复代码。


接下来,我们将探讨 [[nodiscard]] 的一些典型应用场景。

使用 std::optional 和 std::variant 进行重构

它可以在哪些场景中使用?