【问题标题】:When do I use "__attribute__((nonnull))" vs "not_null<T*>"?我什么时候使用“__attribute__((nonnull))”与“not_null<T*>”?
【发布时间】:2016-12-03 03:35:29
【问题描述】:

我习惯于在表达不应为空的指针时使用__attribute__((nonnull))

void f(int* ptr __attribute__((nonnull)));

int main(){
    int* ptr = new int(1);
    f(ptr);
}
void f(int* ptr){/*impl*/}

但是,对于 GSL,还有 not_null&lt;T*&gt; 包装器类型。
void function1(gsl::not_null n);

void f(gsl::not_null<int*> n);

int main(){
    int* ptr = new int(1);
    f(ptr);
}
void f(gsl::not_null<int*> n){/*impl*/}

假设语言设施支持 GSL 版本,我现在应该一直使用not_null&lt;T*&gt; 代替__attribute__((nonnull)) 吗?

我一直认为编译器属性可能有助于优化,但包装器版本解析为一个未归属的指针。

【问题讨论】:

  • 一个问题,__attribute__((nonnull)) 可以跨主要编译器移植吗?
  • 为什么不使用参考或span
  • @WhiZTiM 它至少可以在 GCC 和 Clang 之间移植。

标签: c++ pointers null attributes cpp-core-guidelines


【解决方案1】:

“我现在应该一直使用 not_null 代替 attribute((nonnull)) 吗?

not_null 似乎是更好的方法,原因如下:

__attribute__((nonnull)) 似乎是 gcc 特定的,因此这意味着只有 gcc 可以将此属性用于优化、安全性、安全性、静态代码分析器(等等,你可以命名它)。如果您想使用多个编译器,这使得它不是一个很好的选择。例如,微软有__assume 可以用来实现类似的结果。

gsl::not_null 不是标准模板库的一部分,因此不能保证它在所有编译器上都以相同的方式工作。您可能会发现在某些编译器上它绝对不会做任何特别的事情。然而这是一个更好的选择,因为not_null 可以包装所有编译器变体以获得相同的结果(也可以添加运行时检查)。但是从目前的实现来看(见链接),只支持使用__assume的微软编译器(找不到gcc的实现,但如果你有,那么使用它是一个优势)

【讨论】:

  • gsl::not_null 现在使用 GCC 和 Clang 的功能类似于 MSVC 的 __assume。 OTOH,即 与 nonnull 属性实现的结果相同 - 前者只是一个提示,后者是一个保证。
猜你喜欢
  • 2016-01-23
  • 1970-01-01
  • 2014-01-28
  • 2011-10-14
  • 2013-02-25
  • 2017-03-26
  • 1970-01-01
  • 1970-01-01
  • 2010-11-12
相关资源
最近更新 更多