2016-07-28 60 views
5

Jestem przyzwyczajony do używania __attribute__((nonnull)) podczas wyrażania wskaźników, które nie powinny mieć wartości null.Kiedy używam "__attribute __ ((nonnull))" vs "not_null <T*>"?

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

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

Jednak z GSL, jest także typem not_null<T*> owinięcie.
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*/} 

Zakładając obiekty językowe są tam, aby wspierać wersję GSL, należy zawsze używać not_null<T*> zamiast __attribute__((nonnull)) teraz?

Odniosłem wrażenie, że atrybut kompilatora może pomóc w optymalizacji, ale wersja opakowania rozwiązuje problem z nieprzypisanym wskaźnikiem.

+2

Jedno pytanie, Czy '__attribute __ ((nonnull)) 'przenośny w większych kompilatorach? – WhiZTiM

+0

Dlaczego nie używać referencji lub 'span'? – Jarod42

Odpowiedz

2

„powinien zawsze być używany not_null zamiast atrybut ((niepustych)) teraz

not_null wydaje się lepszym rozwiązaniem, a oto dlaczego:

__attribute__((nonnull)) wydaje się być specyficzne dla gcc, więc oznacza to, że tylko gcc może używać tego atrybutu do optymalizacji, bezpieczeństwa, statycznych analizatorów kodu (itd.), co czyni go niezbyt dobrym wyborem, jeśli chcesz używać wielu kompilatorów. __assume, które można wykorzystać do osiągnięcia podobnych rezultatów.

gsl::not_null nie należy do standardowej biblioteki szablonów, więc nie ma gwarancji, że będzie działał na wszystkich kompilatorach w ten sam sposób. Może się okazać, że w niektórych kompilatorach nie zrobi absolutnie nic specjalnego. Jednak jest to lepszy wybór, ponieważ not_null może zawijać wszystkie warianty kompilatora, aby osiągnąć ten sam wynik (można również dodać sprawdzanie czasu wykonywania). Ale sądząc po obecnej implementacji (patrz link), jest tylko wsparcie dla kompilatora Microsoft używającego __assume (nie można znaleźć implementacji dla gcc, ale jeśli masz, to jest to korzyść z jego używania)

+0

gsl :: not_null używa teraz funkcji GCC i Clang podobnej do __assume MSVC. OTOH, to znaczy * nie * jest identyczne z wynikiem uzyskanym przez atrybut "nonnull" - ten pierwszy jest tylko podpowiedzią, ten ostatni jest gwarancją. –