我什么时候使用“__attribute__((nonnull))”与 "not_null<T*>"?
When do I use "__attribute__((nonnull))" vs "not_null<T*>"?
我习惯于在表达不应为空的指针时使用__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 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<T*>
代替 __attribute__((nonnull))
吗?
我的印象是编译器属性可能有助于优化,但包装器版本解析为未属性指针。
"should I always be using not_null in place of attribute((nonnull)) now?
not_null
似乎是更好的方法,原因如下:
__attribute__((nonnull))
seems to be gcc specific so this means that only gcc could use this attribute for optimizations, safety, security, static code analyzers (etc, you name it). This makes it not a very good choice if you want to use multiple compilers. Microsoft has for example __assume
可用于实现类似的结果。
gsl::not_null
不是标准模板库的一部分,因此不能保证它能以相同的方式在所有编译器上工作。您可能会发现在某些编译器上它不会做任何特别的事情。然而,这是一个更好的选择,因为 not_null
可以包装所有编译器变体以获得相同的结果(也可以添加运行时检查)。但从当前的实现来看(参见 link),仅支持使用 __assume
的 Microsoft 编译器(无法找到 gcc 的实现,但如果你有,那么使用它是一个优势)
我习惯于在表达不应为空的指针时使用__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 function1(gsl::not_null
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))
吗?
我的印象是编译器属性可能有助于优化,但包装器版本解析为未属性指针。
"should I always be using not_null in place of attribute((nonnull)) now?
not_null
似乎是更好的方法,原因如下:
__attribute__((nonnull))
seems to be gcc specific so this means that only gcc could use this attribute for optimizations, safety, security, static code analyzers (etc, you name it). This makes it not a very good choice if you want to use multiple compilers. Microsoft has for example __assume
可用于实现类似的结果。
gsl::not_null
不是标准模板库的一部分,因此不能保证它能以相同的方式在所有编译器上工作。您可能会发现在某些编译器上它不会做任何特别的事情。然而,这是一个更好的选择,因为 not_null
可以包装所有编译器变体以获得相同的结果(也可以添加运行时检查)。但从当前的实现来看(参见 link),仅支持使用 __assume
的 Microsoft 编译器(无法找到 gcc 的实现,但如果你有,那么使用它是一个优势)