Soru C ++’daki beyan noktası


Neden çıkış değil 101 bir önceki atadığım zaman x yeni x?

int x = 101;
{
    int x = x;
    std::cout << x << std::endl;
}

Çıkış (çöp):

422634

İkinci düşündüm x başlatılacak 101  ama başlatılmamış.

Not: Bu durumda çözüm int x = ::x ama soru niye ya olur.


32
2018-04-01 15:26


Menşei


Diye sordum benzer bir şey hakkında son günlerde... - Kerrek SB
En son C ++ 1y taslağı bu tanımlanmamış davranışı da yapar, bkz. Belirsiz değerlerin ve tanımlanmamış davranışların kullanımına göre C ++ 1y değişti mi?. - Shafik Yaghmour


Cevaplar:


Beyan noktası

Bir ismin beyanı tamamlandıktan hemen sonra   declarator ve onun başlatıcısı önce ... [C ++ Standart § 3.3.2 / 1]

Derleyici, declarator hakkında yeterli bilgiye sahip olduğunda bildirimi tamamlar.

Yukarıdaki kod, aşağıdakine eşittir:

int x = 101;
{
  int x;
  x = x; <------------------// Self assignment, assigns an indeterminate value.
  std::cout << x << std::endl;
}

Çünkü iç beyannamesi x daha önce tamamlandı = (Atama)

int x = x; <--// Now, we have the new `x` which hides the older one, 
     ^        // so it assigns itself to itself
     |
     +---// Point of declaration,
         // here compiler knows everything to declare `x`.
         // then declares it.

Öte yandan, karmaşık nesneleri ilan ettiğimizde, beyan etme noktası daha uzundur. Yani davranış farklıdır.

Örneğin, aşağıdaki kod tamam

const int i = 2;
{
  int i[i];
         ^
         |
         +----// Point of declaration
              // compiler has to reach to "]"
              // therefore before declaring `i` as an array
              // there is just one `i`, the `i` of `const int i=2`
}

Yukarıdaki kodda, derleyici bildirimi tamamlamak için dizinin gerçek boyutunu bilmek zorundadır, bu nedenle bildirim noktası ]. Bu yüzden i içinde [i] dış i çünkü beyanı i arasında int i[... henüz tamamlanmadı. Böylece, bir dizi ile bildirir 2 elementler (int i[2];).

Ayrıca bu örnek, bir numaralayıcı için beyan noktasını göstermektedir.

const int x = 12;
{
  enum { x = x };
               ^
               |
               +---// Point of declaration
                   // compiler has to reach to "}" then
                   // there is just one `x`, the `x` of `const int x=12`

}

Sayımcı x sabitin değeri ile başlatılır x, yani 12.


44
2018-04-01 15:26



Belki de c ++ 11 kullanırken de bildirimin tamamlandığını ekleyebiliriz auto anahtar kelime, ve bunun bir hata olduğunu auto x = x - Geoffroy
@Geoffroy: Bir sorum var auto x=x;  İşte - deepmax
Doğrudan başlatıcıları kullanırken, beyan etme noktası ne olurdu? (ör. int x (x)). Microsoft Visual C ++ Derleyici (MSVC 2017) kapanış parenslerinde bildirme noktasını koymaktadır. - Tom
@deepmax Eğer haklıysanız, GCC'nin bir sorunu vardır, çünkü "int i (i)" hiçbir küresel tanımlanmamıştır "i". (sadece uyarı, başlatılmamış) - Tom
@ Tom: Umm, fikrimi değiştireyim, eğer int i(i); gibi int i = i; sonra MSVC yanlıştır. Öyle değil mi? - deepmax


Bunu yapmanın başka bir yolu var.

#include <iostream>
int x = 101;
int main()
{
  int x = ::x;
  std::cout << x << std::endl;
  std::cin.get();
}

9
2018-04-01 15:39



Doğru, ama soru soruyor niye ya, değil Nasıl çözeceksin. - deepmax
@ MM soru "Önceki x'i yeni x'ye atamış olsaydım neden çıktı 101 değil?" - Bu cevap şu soruya cevap olarak görülebilir: "çünkü ismi şu şekilde nitelendirmedin:". Sizinle birlikte (aynı zamanda harika bir cevap) değerli bir cevap IMO'su. - JBentley


değişken kapsam X'in önüne yazılacak. int x = x; Bu iki süreç var. Bir: int x; (x değişkenini tanımlayın ve belleği ayırın ve başlangıç ​​değerini belirtin: x = 0); bu an ön x gizli olacak. İki: x = x; (x değerini bulun);


0
2018-04-01 16:29