"As-eğer" kuralı altın C ++ 1 , devletler eğer gözlemlenebilir davranış bir programın kullanılmayan veri üyeli varlığına bağlı değildir uzağa optimize etmek, derleyici izin verilir .
Kullanılmayan bir üye değişkeni hafızayı alır mı?
Hayır (eğer "gerçekten" kullanılmamışsa).
Şimdi akılda iki soru var:
- Gözlemlenebilir davranış ne zaman bir üyenin varlığına bağlı olmaz?
- Gerçek hayat programlarında bu tür durumlar oluyor mu?
Bir örnekle başlayalım.
Misal
#include <iostream>
struct Foo1
{ int var1 = 5; Foo1() { std::cout << var1; } };
struct Foo2
{ int var1 = 5; int var2; Foo2() { std::cout << var1; } };
void f1() { (void) Foo1{}; }
void f2() { (void) Foo2{}; }
Gcc'den bu çeviri birimini derlemesini istersek , çıktı:
f1():
mov esi, 5
mov edi, OFFSET FLAT:_ZSt4cout
jmp std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
f2():
jmp f1()
f2
ile aynıdır f1
ve gerçeği tutmak için hiçbir bellek kullanılmaz Foo2::var2
. ( Clang benzer bir şey yapar ).
Tartışma
Bazıları bunun iki nedenden dolayı farklı olduğunu söyleyebilir:
- bu çok önemsiz bir örnek
- yapı tamamen optimize edilmiştir, sayılmaz.
İyi bir program, karmaşık şeylerin basit bir şekilde yan yana dizilmesinden ziyade basit şeylerin akıllı ve karmaşık bir birleşimidir. Gerçek hayatta, derleyicinin optimize ettiğinden daha basit yapıları kullanarak tonlarca basit işlev yazarsınız. Örneğin:
bool insert(std::set<int>& set, int value)
{
return set.insert(value).second;
}
Bu, bir veri üyesinin (burada std::pair<std::set<int>::iterator, bool>::first
) kullanılmamış olmasının gerçek bir örneğidir . Bil bakalım ne oldu? Optimize edilmiştir ( bu montaj sizi ağlatırsa bir kukla set ile daha basit bir örnek ).
Şimdi , Max Langhof'un mükemmel cevabını okumak için mükemmel bir zaman (lütfen benim için oy verin). Sonuçta yapı kavramının derleyicinin çıkardığı montaj düzeyinde neden anlamsız olduğunu açıklar.
"Ancak, X yaparsam, kullanılmayan üyenin optimize edilmiş olması bir sorun olur!"
Bu cevabın yanlış olması gerektiğini savunan çok sayıda yorum yapılmıştır çünkü bazı işlemler (benzeri assert(sizeof(Foo2) == 2*sizeof(int))
) bir şeyi bozabilir.
X, program 2'nin gözlemlenebilir davranışının bir parçasıysa , derleyicinin şeyleri optimize etmesine izin verilmez. "Kullanılmayan" bir veri üyesi içeren bir nesne üzerinde, program üzerinde gözlemlenebilir bir etkiye sahip olan birçok işlem vardır. Böyle bir işlem gerçekleştirilirse veya derleyici hiçbirinin gerçekleştirilmediğini kanıtlayamazsa, bu "kullanılmayan" veri üyesi, programın gözlemlenebilir davranışının bir parçasıdır ve optimize edilemez .
Gözlemlenebilir davranışı etkileyen işlemler aşağıdakileri içerir, ancak bunlarla sınırlı değildir:
- bir tür nesnenin boyutunu almak (
sizeof(Foo)
),
- "Kullanılmamış" olandan sonra beyan edilen veri üyesinin adresini almak,
- gibi bir işlev ile bir nesne kopyalama
memcpy
,
- nesnenin temsilini değiştirmek (ile olduğu gibi
memcmp
),
- bir nesneyi uçucu olarak nitelendirmek ,
- vb .
1)
[intro.abstract]/1
Bu belgedeki anlamsal açıklamalar, parametreleştirilmiş, kesin olmayan bir soyut makineyi tanımlar. Bu belge, uyumlu uygulamaların yapısına herhangi bir gereklilik getirmemektedir. Özellikle, soyut makinenin yapısını kopyalamaları veya taklit etmeleri gerekmez. Daha ziyade, uyumlu uygulamaların aşağıda açıklandığı gibi soyut makinenin gözlemlenebilir davranışını taklit etmesi (sadece) gereklidir.
2) Bir iddianın geçmesi veya kalması gibi.