2016-11-23 12 views
14

gcc dokumentacja __attribute__((pure)) stanów:adnotacji const funkcji członka z czystej atrybutu

Wiele funkcji nie mają skutków oprócz wartości zwracanej, a ich wartość powrotu zależy tylko od parametrów i/lub zmiennych globalnych. Taka funkcja może być przedmiotem wspólnej eliminacji wyrażeń i optymalizacji pętli, tak jak byłoby to możliwe w przypadku operatora arytmetycznego. Funkcje te powinny być zadeklarowane z atrybutem pure.

Co to znaczy, że zależy tylko od parametrów? Rozważmy:

struct Wrapper { 
    int i; 

    int get() const { return i; } 
    void set(int x) { i = x; } 
}; 

Czy to ważne, aby oznaczyć Wrapper::get() jako funkcja pure członkiem? To zależy tylko od niejawnej instancji Wrapper, ale dane mogą się zmienić.

+1

Ten artykuł może być istotny pod adresem http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0078r0.pdf – Danh

+1

Niejawny obiekt (ten) jest nadal parametrem. Składnia jest nieistotna. Zadzwoń, jeśli foo (x) lub x.foo() lub cokolwiek innego. –

+0

@Danh Z artykułu nie jest całkowicie jasne, jaka jest odpowiedź na to pytanie. Wydaje się nieco niezobowiązujące. – Barry

Odpowiedz

4

Czy można oznaczać etykietą Wrapper::get() jako funkcję składową pure? To zależy tylko od niejawnej instancji Wrapper, ale dane mogą się zmienić.

Tak, Wrapper::get() spełnia wymagania atrybutu gcc pure. Należy jednak zauważyć, że __attribute__((pure)) nie oznacza czystego w sensie akademickim, tj. Posiadającym właściwość transparentności referencyjnej. Te ostatnie mogą być przekazywane poprzez zaostrzenie __attribute__((const)):

__attribute__((const))

Wiele funkcji nie bada wszelkie wartości z wyjątkiem ich argumentów, a nie mają skutków oprócz wartości zwracanej. Zasadniczo jest to po prostu nieco bardziej rygorystyczna klasa niż atrybut pure poniżej, ponieważ funkcja nie może odczytać pamięci globalnej.

Zauważ, że funkcja, która ma argumenty wskaźnik i analizuje dane wskazał do moszczu nie zostać uznana const. Podobnie funkcja, która wywołuje , a nie jest funkcją const, zwykle nie może być const. Nie ma sensu funkcja dla funkcji do zwracania void.

Ale ponieważ Wrapper::get() nie posiada własność referencyjnym przejrzystości domniemanych przez __attribute__((const)), to nie może być oznaczone jako takie.

EDIT

Gwarancja o pure -ness (w sensie GCC) z funkcji mogą być wykorzystywane do optymalizacji tylko blok kodu, który nie zawiera zapisy do pamięci globalnej (aw szczególności , nie jest przerywane wywołaniami funkcji innych niż pure). Przykłady:

struct Wrapper { 
    int i; 

    int get() const __attribute__((pure)) { return i; } 
    void set(int x) { i = x; } 
}; 

long foo(Wrapper* w) 
{ 
    // w->get() can be computed once 
    return 2 * w->get() * w->get(); 
} 

long bar(Wrapper* w) 
{ 
    // w->get() can be computed once (even though below code writes to memory, 
    // that memory is freshly allocated and cannot be accessed by w->get()) 
    long result = 2; 
    result *= w->get(); 
    result *= w->get(); 
    return result; 
} 

long baz(Wrapper* w) 
{ 
    // both w->get()s must be evaluated, since non-pure code occurs between them 
    long result = 2; 
    result *= w->get(); 
    std::cout << "Result after the first muliplication: " << result << std::endl; 
    result *= w->get(); 
    return result; 
} 
+0

Jesteś pewien o '__attribute __ ((const))? Czy nie jest domniemany "this" argument wskaźnika dla funkcji? – Barry

+0

@Barry Zobacz zaktualizowaną odpowiedź – Leon

+0

Nie jestem pewien, czy dodanie pojęcia "referencyjna przezroczystość" pomaga. Czy to określenie ma nawet określone znaczenie? Czy 'strlen()' nie jest referencyjnie przezroczysty? – Barry

Powiązane problemy