Myślę, że czegoś tu brakuje.
funkcja statyczna?
Zadeklarowanie funkcji statycznej spowoduje, że będzie ona „ukryta” w jednostce kompilacji.
Nazwa mająca zasięg przestrzeni nazw (3.3.6) ma łącze wewnętrzne, jeśli jest nazwą
- zmienna, funkcja lub szablon funkcji, który jest jawnie zadeklarowany jako statyczny;
3.5 / 3 - C ++ 14 (n3797)
Gdy nazwa ma powiązania wewnętrzne, do jednostki, którą ona oznacza, można odnieść się za pomocą nazw z innych zakresów w tej samej jednostce tłumaczeniowej.
3.5 / 2 - C ++ 14 (n3797)
Jeśli zadeklarujesz tę statyczną funkcję w nagłówku, wszystkie jednostki kompilacji, w tym ten nagłówek, będą miały własną kopię funkcji.
Rzecz w tym, że jeśli wewnątrz tej funkcji znajdują się zmienne statyczne, każda jednostka kompilacji zawierająca ten nagłówek będzie miała również swoją własną, osobistą wersję.
funkcja inline?
Zadeklarowanie go inline sprawia, że jest on kandydatem do wstawiania (w dzisiejszych czasach w C ++ nie znaczy to wiele, ponieważ kompilator będzie wbudowany lub nie, czasami ignorując fakt, że słowo kluczowe inline jest obecne lub nieobecne):
Deklaracja funkcji (8.3.5, 9.3, 11.3) ze specyfikatorem wbudowanym deklaruje funkcję wbudowaną. Specyfikator wbudowany wskazuje implementacji, że podstawianie w wierszu treści funkcji w punkcie wywołania ma być preferowane w stosunku do zwykłego mechanizmu wywoływania funkcji. Implementacja nie jest wymagana, aby wykonać to podstawienie w linii w momencie wywołania; jednakże, nawet jeśli to podstawianie w wierszu zostanie pominięte, pozostałe reguły funkcji wbudowanych, zdefiniowane w 7.1.2, powinny być nadal przestrzegane.
7.1.2 / 2 - C ++ 14 (n3797)
W nagłówku ma to interesujący efekt uboczny: wbudowaną funkcję można zdefiniować wiele razy w tym samym module, a linker po prostu połączy „je” w jeden (jeśli nie zostały one wstawione z powodu kompilatora).
W przypadku zmiennych statycznych zadeklarowanych wewnątrz standard wyraźnie podaje jedną i tylko jedną z nich:
Statyczna zmienna lokalna w zewnętrznej funkcji wbudowanej zawsze odnosi się do tego samego obiektu.
7.1.2 / 4 - C ++ 98 / C ++ 14 (n3797)
(funkcje są domyślnie extern, więc jeśli nie oznaczysz swojej funkcji jako statycznej, dotyczy to tej funkcji)
Ma to tę zaletę, że jest „statyczne” (tj. Można je zdefiniować w nagłówku) bez wad (istnieje najwyżej raz, jeśli nie jest wstawione)
statyczna zmienna lokalna?
Statyczne zmienne lokalne nie mają żadnych powiązań (nie można do nich odwoływać się z nazwy poza swoim zakresem), ale mają statyczny czas przechowywania (tj. Są globalne, ale ich konstrukcja i niszczenie podlegają określonym regułom).
statyczne + wbudowane?
Mieszanie inline i static będzie miało konsekwencje, które opisałeś (nawet jeśli funkcja jest wbudowana, zmienna statyczna wewnątrz nie będzie, a skończysz z tyloma zmiennymi statycznymi, ile masz jednostek kompilacji, w tym definicję funkcji statycznych ).
Odpowiedz na dodatkowe pytanie autora
Odkąd napisałem pytanie, wypróbowałem to w Visual Studio 2008. Próbowałem włączyć wszystkie opcje, które sprawiają, że VS działa zgodnie ze standardami, ale możliwe, że niektóre mi ominęły. Oto wyniki:
Gdy funkcja jest tylko „wbudowana”, istnieje tylko jedna kopia zmiennej statycznej.
Gdy funkcja jest „statyczna w wierszu”, kopii jest tyle, ile jest jednostek tłumaczeniowych.
Prawdziwe pytanie brzmi teraz, czy tak ma być, czy też jest to cecha charakterystyczna kompilatora Microsoft C ++.
Więc przypuszczam, że masz coś takiego:
void doSomething()
{
static int value ;
}
Musisz zdać sobie sprawę, że zmienna statyczna wewnątrz funkcji, po prostu jest to zmienna globalna ukryta dla wszystkich oprócz zakresu funkcji, co oznacza, że tylko funkcja, w której jest zadeklarowana, może do niej dotrzeć.
Umieszczenie funkcji niczego nie zmieni:
inline void doSomething()
{
static int value ;
}
Będzie tylko jedna ukryta zmienna globalna. Fakt, że kompilator będzie próbował wstawić kod, nie zmieni faktu, że istnieje tylko jedna globalna zmienna ukryta.
Teraz, jeśli twoja funkcja jest zadeklarowana jako statyczna:
static void doSomething()
{
static int value ;
}
Wtedy jest „prywatna” dla każdej jednostki kompilacji, co oznacza, że każdy plik CPP, w tym nagłówek, w którym zadeklarowana jest funkcja statyczna, będzie miał swoją prywatną kopię funkcji, w tym własną prywatną kopię globalnej ukrytej zmiennej, a więc tyle zmiennych, ile istnieją jednostki kompilacji zawierające nagłówek.
Dodanie „inline” do funkcji „static” ze zmienną „static” wewnątrz:
inline static void doSomething()
{
static int value ;
}
ma taki sam skutek, jak brak dodania tego słowa kluczowego „inline”, jeśli chodzi o zmienną statyczną wewnątrz.
Zatem zachowanie VC ++ jest poprawne, a Ty mylisz prawdziwe znaczenie słów „inline” i „static”.