我什么时候使用 "__attribute__((nonnull))" vs "not_null<T*>"?

When do I use "__attribute__((nonnull))" vs "not_null<T*>"?

本文关键字:什么时候 lt gt null nonnull vs not attribute      更新时间:2023-10-16

我习惯于在表达不应该为null的指针时使用__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<T*>包装器类型
void函数1(gsl::not_null<int*>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<T*>代替__attribute__((nonnull))吗?

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

"我现在应该一直使用not_null来代替属性((nonnull))吗?

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

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

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