Arasındaki fark nedir
int x=7;
ve
register int x=7;
?
C ++ kullanıyorum.
Arasındaki fark nedir
int x=7;
ve
register int x=7;
?
C ++ kullanıyorum.
registeroylaması, C ve C ++ arasında farklı anlamlara sahiptir.
register int a[1];bu bildirimle, bu diziyi indeksleyemezsiniz.
Yanıtlar:
2010'da olduğu gibi C ++ 'da, "otomatik" veya "kayıt" anahtar kelimelerini kullanan geçerli herhangi bir program, bu anahtar kelimeler kaldırılmış olanla semantik olarak aynı olacaktır (dizgeli makrolarda veya diğer benzer bağlamlarda görünmedikçe). Bu anlamda, anahtar kelimeler düzgün derlenen programlar için işe yaramaz. Öte yandan, bir makronun uygunsuz kullanımının sahte kod üretmek yerine derleme zamanı hatasına neden olmasını sağlamak için anahtar sözcükler belirli makro bağlamlarında yararlı olabilir.
C ++ 11 ve dilin sonraki sürümlerinde, autoanahtar sözcük, başlatılan nesneler için sözde tür olarak hareket etmek üzere yeniden amaçlanmıştır ve bir derleyici otomatik olarak başlatan ifadenin türüyle değiştirecektir. Bu nedenle, C ++ 03'te bildirim: bir blok bağlamı içinde kullanıldığında auto int i=(unsigned char)5;ile eşdeğerdi int i=5;ve auto i=(unsigned char)5;bir kısıtlama ihlaliydi. C ++ 11'de,auto int i=(unsigned char)5; ise bir kısıtlama ihlali haline auto i=(unsigned char)5;denk oldu auto unsigned char i=5;.
autobasitçe ihmal edilemez ... Belki cevabınızı güncelleyebilirsiniz.
registerkullanımdan kaldırıldı ve C ++ 17 için kaldırılması için bir teklif yapılacak.
autoartık otomatik tür çıkarımı için kullanılıyor. Ancak ondan önce, değişkeninizin "otomatik olarak" saklanmasını istediğinizi belirtmek için kullanıldı ( bu nedenle, sanırım yığında ) anahtar sözcüğün aksine register("işlemcinin kaydı" anlamına gelir):
register derleyiciye bu değişkeni bellek yerine bir işlemci kaydında saklamasını tavsiye eden bir ipucudur (örneğin, yığın yerine).
Derleyici bu ipucunu takip edebilir veya takip etmeyebilir.
Herb Sutter'a göre " Olmayan Anahtar Kelimeler (veya Başka İsimle Yapılan Yorumlar)" :
Bir kayıt belirticisi, bir otomatik belirtici ile aynı anlam bilgisine sahiptir ...
storage-class-specifierdilbilgisinde yer alanlardan biri değildir ve tanımlanmış bir semantiği yoktur. Uyumlu bir derleyici, Clang'ın yaptığı gibi bir hata atabilir. Yine de bazı uygulamalar buna izin veriyor ve ya yok sayıyor (MSVC, ICC) ya da bir optimizasyon ipucu (GCC) olarak kullanıyor. Open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0001r1.html adresine bakın . Yine de bir noktada yanlış konuştum: C ++ 11'de kullanımdan kaldırıldı.
Göre Herb Sutter , register"bir boşluk olarak aynen anlamlı " ve C ++ programının semantik üzerinde hiçbir etkisi yoktur.
Neredeyse kesinlikle hiçbir şey.
registerderleyiciye xçok kullanmayı planladığınız ve bir kayıt defterine yerleştirilmesi gerektiğini düşündüğünüz bir ipucudur .
Ancak, derleyiciler artık kayıtlara hangi değerlerin yerleştirilmesi gerektiğini belirlemede ortalama (hatta uzman) bir programcının olduğundan çok daha iyidir, bu nedenle derleyiciler anahtar kelimeyi görmezden gelir ve istediklerini yapar.
registerC ++ 11'de kullanımdan kaldırılmıştır. Kullanılmamış ve C ++ 17'de saklıdır.
registerAnahtar kelime için yararlı oldu:
registerAnahtar kelimenin gerekli olduğu verimli bir sistem örneği :
typedef unsigned long long Out;
volatile Out out,tmp;
Out register rax asm("rax");
asm volatile("rdtsc":"=A"(rax));
out=out*tmp+rax;
C ++ 11'den beri kullanımdan kaldırıldı ve kullanılmıyor ve C ++ 17'de saklanıyor .
registerdepolama sınıfı belirticisinden farklı olan ve GCC tarafından hala desteklenen Explicit Register Variables uzantısını kullanıyor .
Gcc 9.3'ten itibaren, kullanarak derleme -std=c++2a, register bir derleyici uyarısı üretir, ancak yine de istenen etkiye sahiptir ve bu yanıt registeraçısından -O1 –- olmadan derleme yaparken C'lere benzer şekilde davranır . Ancak clang ++ - 7 kullanımı bir derleyici hatasına neden olur. Yani evet,register optimizasyonlar sadece optimizasyon -O işaretleri olmadan standart derlemede bir fark yaratır, ancak bunlar derleyicinin -O1 ile bile anlayacağı temel optimizasyonlardır.
Tek fark, C ++ 'da, kayıt değişkeninin adresini almanıza izin verilmesidir; bu, optimizasyonun yalnızca değişkenin adresini veya takma adlarını (bir işaretçi oluşturmak için) veya bir referans almadığınızda gerçekleşeceği anlamına gelir. kodda (sadece - O0, çünkü bir referansın da bir adresi vardır, çünkü bu , -Ofast kullanarak derleme yapılıyorsa yığının dışında bir işaretçi gibi optimize edilebilen bir işaretçi gibi bir sabit işaretçisidir , ancak hiçbir zaman görünmezler) -Ofast kullanarak yığında, çünkü bir göstericinin aksine, yapılamazlar volatileve adresleri alınamaz), aksi takdirde kullanmamış gibi davranacaktırregister ve değer yığın üzerinde saklanacaktır.
-O0'da diğer bir fark, const registergcc C ve gcc C ++ 'da aynı şekilde davranmaz. Gcc C'de şu şekilde const registerdavranır register, çünkü blok kapsamları constgcc üzerinde optimize edilmemiştir. Clang C'de registerhiçbir şey yapmaz ve yalnızca constblok kapsamı optimizasyonları geçerlidir. Gcc C'de registeroptimizasyonlar geçerlidir ancak constblok kapsamında optimizasyon yoktur. Gcc C üzerinde ++, hem registerve constblok-kapsam optimisations birleştirir.
#include <stdio.h> //yes it's C code on C++
int main(void) {
const register int i = 3;
printf("%d", i);
return 0;
}
int i = 3;:
.LC0:
.string "%d"
main:
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-4], 3
mov eax, DWORD PTR [rbp-4]
mov esi, eax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, 0
leave
ret
register int i = 3;:
.LC0:
.string "%d"
main:
push rbp
mov rbp, rsp
push rbx
sub rsp, 8
mov ebx, 3
mov esi, ebx
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, 0
mov rbx, QWORD PTR [rbp-8] //callee restoration
leave
ret
const int i = 3;
.LC0:
.string "%d"
main:
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-4], 3 //still saves to stack
mov esi, 3 //immediate substitution
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, 0
leave
ret
const register int i = 3;
.LC0:
.string "%d"
main:
push rbp
mov rbp, rsp
mov esi, 3 //loads straight into esi saving rbx push/pop and extra indirection (because C++ block-scope const is always substituted immediately into the instruction)
mov edi, OFFSET FLAT:.LC0 // can't optimise away because printf only takes const char*
mov eax, 0 //zeroed: https://stackoverflow.com/a/6212755/7194773
call printf
mov eax, 0 //default return value of main is 0
pop rbp //nothing else pushed to stack -- more efficient than leave (rsp == rbp already)
ret
registerderleyiciye 1) yerel bir değişkeni, bu durumda aranan uca kaydedilmiş bir kayıtta saklamasını rbxve 2) değişken adresi hiçbir zaman alınmazsa yığın yazmalarını optimize etmesini söyler . constderleyiciye değeri hemen değiştirmesini (ona bir kayıt atamak veya bellekten yüklemek yerine) ve yerel değişkeni varsayılan davranış olarak yığına yazmasını söyler .const registerbu cesaretlendirilmiş optimizasyonların birleşimidir. Bu olabildiğince ince.
Ayrıca, gcc C ve C ++ üzerinde, yığındaki ilk yerel için yığın registerüzerinde kendi başına rastgele 16 baytlık bir boşluk yaratıyor gibi görünüyor , bu daconst register .
Ancak -Ofast kullanarak derleme; register0 optimizasyon etkisine sahiptir, çünkü bir sicile koyulabilir veya anında yapılabilirse, her zaman olacaktır ve olamazsa olmayacak; constyine de C ve C ++ üzerindeki yükü optimize eder, ancak yalnızca dosya kapsamında ; volatileyine de değerleri yığından depolanmaya ve yüklenmeye zorlar.
.LC0:
.string "%d"
main:
//optimises out push and change of rbp
sub rsp, 8 //https://stackoverflow.com/a/40344912/7194773
mov esi, 3
mov edi, OFFSET FLAT:.LC0
xor eax, eax //xor 2 bytes vs 5 for mov eax, 0
call printf
xor eax, eax
add rsp, 8
ret
Derleyicinin iyileştiricisinin iki değişkene sahip olduğu ve birini yığına dökmeye zorlandığı bir durumu düşünün. Öyle oldu ki, her iki değişken de derleyici için aynı ağırlığa sahip. Fark olmadığı için, derleyici değişkenlerden birini keyfi olarak yayacaktır. Öte yandan,register anahtar kelime derleyiciye hangi değişkene daha sık erişileceği konusunda ipucu verir. X86 önceden getirme talimatına benzer, ancak derleyici iyileştirici içindir.
Açıkça register ipuçları, kullanıcı tarafından sağlanan dallanma olasılığı ipuçlarına benzer ve bu olasılık ipuçlarından çıkarılabilir. Derleyici bazı dalların sıklıkla alındığını bilirse, dalla ilgili değişkenleri kayıtlarda tutacaktır. Bu yüzden dal ipuçlarını daha fazla önemsemenizi ve unutmayı öneriyorum register. İdeal olarak profil uzmanınız derleyiciyle bir şekilde iletişim kurmalı ve sizi bu tür nüanslar hakkında düşünmekten bile kurtarmalıdır.