web-gelistirme-sc.com

statik vs ad alanındaki statik olmayan değişkenler

foo bir tamsayı içeren bar ad alanına sahip, böylece bildirilmiş ...

foo.h:

namespace foo {
    int bar;
}

Şimdi eğer sadece bir dosyaya foo.h eklersem, bu iyi sonuç verir. Ancak iki veya daha fazla dosyadan foo.h eklediğimde bir sorun ortaya çıkıyor: Bir bağlayıcı hatası alıyorum. bar __static olarak ilan edersem, foo.h'yi birden fazla dosyaya dahil edebileceğimi düşündüm. Bu bana çok garip geliyor çünkü birinin ad alanının içerisinde statik bir değişken olduğunu açıklayabileceğini bilmiyordum. (Bu ne anlama geliyor?)

Bu neden işe yarıyor? Ve daha önemlisi, neden çalışmıyor o olmadanstatic? static __ 'de kullanıldığında namespace ne anlama geliyor?

34
Michael Dorst

Farklı bağlamlarda static için çok sayıda anlam vardır. Bu özel bağlamda, değişkenin iç bağı olduğu anlamına gelir ve bu nedenle bu başlığı içeren her çeviri birimi değişkenin kendi kopyasına sahip olur.

Bu, linker hatasını susturacak olsa da, oluşturulan nesne dosyalarının her biri için ayrı bir foo::bar değişkeninin korunacağını unutmayın (değişiklikler, farklı nesne dosyaları arasında görünmez).

Tek bir değişken istiyorsanız, bunu başlıktaki extern olarak bildirmeli ve bir çeviri biriminde tek bir tanım sağlamalısınız.

Bir değişkeni static olarak bildirdiğinizde, kapsamının verilen çeviri birimi ile sınırlı olduğu anlamına gelir. static olmadan kapsam globaldir.

Bir değişkeni bir .h dosyasının içine static olarak bildirirseniz (namespace; içinde veya olmadan önemli değildir) ve bu başlık dosyasını çeşitli .cpp dosyalarına dahil ettiğinizde, static değişkeni .cpp dosyalarının her biri için yerel olarak kapsamlanır.
Şimdi, bu başlığı içeren her .cpp dosyası bu değişkenin kendi kopyasına sahip olacaktır.

static anahtar sözcüğü olmadan, derleyici bu değişkenin yalnızca bir kopyasını oluşturur, böylece başlık dosyasını birden fazla .cpp dosyasına dahil ettiğinizde linker birden çok tanımdan şikayet eder.

24
iammilind

Problem, değişkenin birden fazla tanımına sahip olmasından kaynaklanır. Farklı çeviri birimlerindeki tanımlar birbiriyle çakışır, tıpkı satır içi olmayan işlev tanımlarının çalışmadığı gibi.

Değişkenleri statik yaptığınızda, değişken iç bağlantıyı verirsiniz, böylece her çeviri biriminin kendi bağımsız kopyası vardır.

Muhtemelen gerçekten istediğiniz şey, yalnızca bir başlığa bildirimi koymak (harici kullanarak) ve sonra tanımı bir uygulama dosyasına koymaktır.

4
bames53

Ayrıca C++ 'daki ad alanında (global) kapsamındaki const int öğesinin varsayılan olarak dolaylı olarak eklenen static seçeneğine sahip olduğunu unutmayın: C++ başlığında sabit değişkenleri tanımla

Neler olduğunu daha iyi anlamak için, derlemenin ara ELF nesne dosyalarında readelf yapın ve sembollerin iki kez tanımlanıp tanımlanmadığını açıkça göreceksiniz. İşte ayrıntılı bir örnek: "statik" C de ne anlama geliyor?