You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于[[nodiscard]]属性在GCC与Clang下编译差异的技术问询

问题:[[nodiscard]]属性的误用与跨编译器行为差异

我尝试使用[[nodiscard]]属性禁止忽略A::create()的返回值,编写的代码如下:

#include <iostream>
#include <memory>

class A
{
public:
    static [[nodiscard]] std::unique_ptr<A> create();
    virtual int get_version() = 0;
    virtual ~A() = default;
};

class B : public A
{
public:
    [[nodiscard]] int get_version() override
    {
        return 20;
    }
};

std::unique_ptr<A>
A::create()
{
    return std::make_unique<B>();
}

int main()
{
    auto a = A::create();
    [[maybe_unused]] int v  = a->get_version();
}

测试环境

  • GCC版本:8.5
  • Clang版本:15.0.0
  • 编译选项:-O3 -std=c++17

各编译器输出

GCC输出

<source>:7:12: warning: attribute ignored [-Wattributes]
     static [[nodiscard]] std::unique_ptr<A> create();
            ^
<source>:7:12: note: an attribute that appertains to a type-specifier is ignored
ASM generation compiler returned: 0
<source>:7:12: warning: attribute ignored [-Wattributes]
     static [[nodiscard]] std::unique_ptr<A> create();
            ^
<source>:7:12: note: an attribute that appertains to a type-specifier is ignored
Execution build compiler returned: 0
Program returned: 0

Clang输出

<source>:7:14: error: 'nodiscard' attribute cannot be applied to types
    static [[nodiscard]] std::unique_ptr<A> create();
             ^
1 error generated.
ASM generation compiler returned: 1
<source>:7:14: error: 'nodiscard' attribute cannot be applied to types
    static [[nodiscard]] std::unique_ptr<A> create();
             ^
1 error generated.
Execution build compiler returned: 1

MSVC输出

该代码在MSVC v19.33下可正常编译,无任何错误或警告。

疑问

请问我是否误用了[[nodiscard]]属性?为何不同编译器会出现这样的行为差异?


回答

你确实误用了[[nodiscard]]属性

在C17标准里,[[nodiscard]]仅允许修饰函数、枚举类或类,用来标记它们的返回值(或实例)不应被忽略。你当前的写法把[[nodiscard]]放在返回类型std::unique_ptr<A>前面,编译器会判定你试图修饰类型——而C17并不支持用[[nodiscard]]修饰类型(这个特性要到C++20才引入)。

正确的写法应让[[nodiscard]]明确修饰函数,以下两种写法都符合C++17标准:

// 写法1:属性放在函数返回类型之后
static std::unique_ptr<A> [[nodiscard]] create();

// 写法2:属性放在函数修饰符(static)之后、返回类型之前
[[nodiscard]] static std::unique_ptr<A> create();

不同编译器行为差异的原因

  1. 标准合规性处理不同:

    • Clang 15严格遵循C++17标准,直接报错指出[[nodiscard]]不能应用于类型,拒绝编译。
    • GCC 8.5同样识别到写法不符合标准,但仅给出警告提示属性被忽略,仍继续编译。
    • MSVC v19.33做了语法扩展,将你代码中的[[nodiscard]]解析为修饰函数而非类型,因此能正常通过编译。
  2. 属性解析逻辑差异:
    你的代码中[[nodiscard]]处于static和返回类型之间,GCC和Clang按照标准语法将其绑定到了后续的类型;而MSVC的解析逻辑更宽松,将其绑定到了函数,这就导致了跨编译器的行为不一致。

内容的提问来源于stack exchange,提问作者kiner_shah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 19:50:25