2014-06-19 15 views
7

this C++ SSS ne iletmeyi dener? Statik bir üyenin adresini ele geçirme C++ SSS

You can take the address of a static member if (and only if) it has an out-of-class definition :

class AE { 
    // ... 
public: 
    static const int c6 = 7; 
    static const int c7 = 31; 
}; 

const int AE::c7; // definition 

int f() 
{ 
    const int* p1 = &AE::c6; // error: c6 not an lvalue 
    const int* p2 = &AE::c7; // ok 
    // ... 
} 

Ancak bu compiles !

+1

"AE" ve "f()" sınıflarını ayrı ayrı derler ve sonra nesnelere bağlarsanız ne olur? – juanchopanza

+1

@juanchopanza '-O2' ile derler ve' f() 'aslında bir noptur. Ancak, orijinal programın -O0 ile yaptığı gibi -O0 'ile bir bağlayıcı hatası verir. – Csq

+0

@Csq Evet, cevabınızı gördüm ve oyladım. Alternatif olarak, std :: cout << p1 << std :: endl; 'bir op yapardı. – juanchopanza

cevap

5

SSS açıklama çok yanıltıcı kullanmaya başlarsanız

Ayrıca bağlayıcı hatası alıyorum; AE::c6 ve AE::c7 her ikisi de değerlerdir. AE::c7, hiçbir tanım yoksa söz konusu kod bir tanım kuralı ihlal: aslında nesnenin adresi gerektiği derleyici eğer Uygulamada

An expression is potentially evaluated unless it is an unevaluated operand or a subexpression thereof. A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression and the lvalue-to-rvalue conversion is immediately applied. [...]

[...]

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required.

, bağlayıcı genellikle bir hata üretecektir. kasanızda, p2 daha sonra kullanılmazsa, optimizasyon p1 tanımını kaldıracağından derleyici adresine gereksinim duymaz. Hiçbir hemen lvalue-to-rvalue dönüşüm olmayacak, std::vector<>::push_back yana

std::vector<int> v; 
v.push_back(AE::c6); 

bir başvuru alır ve bir tanım gerekli geçerli: Bu durumda Daha da daha sık vaka aşağıdaki gibi şeylerdir. Uygulamada, std::vector<>::push_back bir şablon işlevidir (genellikle satır içi), bu nedenle derleyici, uygulamasının içine girebilir ve değeri gerçek değerine dönüştürür ve gerçek değerdegerçek değere dönüştürülür. Kod derlenecek ve çalışacaktır. Ama yine de resmen tanımlanmamış bir davranış.

9

Sen derlemek için -O2 kullanın. Derleyici const int* p1 = &AE::c6; atamalarını (hiçbir etkisi olmadığı için) en iyi duruma getirebilir ve bu nedenle son kodda AE::c6 adresine ihtiyaç duymaz, bu yüzden derler.

Optimizasyon olmadan bir bağlayıcı hatası verir. Eğer p1 (örn std::cout << p1 << p2 << std::endl;) Link

+0

Tamam, ben de burada aynı şeyi söyleyeyim (ben silindi cevabından biriydi), yorum yap * // hata: c6 SSS'de bir lvalü değil IMO, ilk bakışta sözdizimsel bir hata gibi görünen yanıltıcıdır. Linker hatası belirgindi, ancak optimizasyondan sonra bana şaşırtıcı bir şekilde bilinmiyordu – P0W

İlgili konular