SORU
16 EYLÜL 2015, ÇARŞAMBA


Kendi kurucu tüzel içine C bir nesne geçiyor?

Aşağıdaki çalışan yanlışlıkla keşfetmek için şaşırdım:

#include <iostream>            
int main(int argc, char** argv)
{
  struct Foo {
    Foo(Foo& bar) {
      std::cout << &bar << std::endl;
    }
  };
  Foo foo(foo); // I can't believe this works...
  std::cout << &foo << std::endl; // but it does...
}

Kendi kurucu inşa edilen nesnenin adresi taşıyorum. Bu kaynak düzeyinde dairesel bir tanım gibi görünüyor. Standartları çok nesneyi bile inşa edilir ya da bu tanımsız davranıştır önce bir işlev bir nesne geçmek için izin?

Tüm sınıf üye fonksiyonları zaten örtülü bir parametre olarak sınıf örneği için veri gösterici olarak verilmiş garip değil sanırım. Ve veri üyeleri düzeni derleme zamanında giderilmiştir.

Unutmayın, bu işe yarar ya da iyi bir fikir değil, sadece daha fazla sınıfları hakkında bilgi edinmek için uğraşıyorum diye sormuyorum.

CEVAP
16 EYLÜL 2015, ÇARŞAMBA


Bu foo standart tarafından izin verilen bir şekilde kullanıyor uninitialzed olmasına rağmen tanımsız davranış değildir. Tam olarak başlatılmadan önce bir uzay nesnesi için ayrılmış sonra ama sınırlı şekilde kullanmak için izin verilir. Her iki değişken için bir referans bağlayıcı ve adresini almaya izin verilir.

Bu diyor ki defect report 363 ile kaplıdır:

Ve eğer, UDT-başlatma self anlamı nedir? Örneğin

 #include <stdio.h>

 struct A {
        A()           { printf("A::A() %p\n",            this);     }
        A(const A& a) { printf("A::A(const A&) %p %p\n", this, &a); }
        ~A()          { printf("A::~A() %p\n",           this);     }
 };

 int main()
 {
  A a=a;
 }

derlenmiş ve baskılar

A::A(const A&) 0253FDD8 0253FDD8
A::~A() 0253FDD8

ve karar çıktı:

3.8 [temel.yaşam] 6 paragraf başvurular burada geçerli olduğunu gösterir. Tam olarak başlatılmadan önce bir sınıf nesnesinin adresi almak için izin, ve bir referans parametre için bir bağımsız değişken olarak başvuru bağlayabilirsiniz sürece doğrudan aktarmak için izin. İşaretçileri printfs %p * void döküm hatası hariç, bu örnekler, standart-uyumlu.

Bölüm tam alıntı 8**[temel.yaşam]şöyle: taslak C 14 standart

Bir nesnenin ömrü başlamadan önce benzer şekilde, ama sonra nesne tahsis edilmiştir ya, sonra işgal edecek olan depolama bir nesnenin ömür boyu olan ve daha önce depolama sona erdi nesne yeniden işgal ya da, başvuran herhangi bir glvalue yayınlandı orijinal nesne ama sadece sınırlı bir şekilde kullanılabilir. Bir nesne için inşaat ya da yıkım altında, 12.7 bakın. Aksi halde, böyle bir glvalue ayrılan depolama (3.7.4.2) ve özelliklerini kullanarak ifade eder değerini bağlı olmayan glvalue tanımlanmış durumda. Program tanımsız davranış varsa:

  • lvalue-rvalue dönüşüm (4.1) böyle bir glvalue, uygulanır

  • bu glvalue statik olmayan veri üyesi erişim veya statik olmayan bir üye fonksiyonu çağırmak için kullanılır nesne, ya da

  • bu glvalue sanal bir temel sınıf için bir referans (8.5.3) bağlı, ya da

  • bu glvalue typeid işlenen bir dynamic_cast (5.2.7) işlenen veya kullanılır.

Yukarıdaki mermi tarafından tanımlandığı gibi tanımsız davranış altında kalan foo hiçbir şey yapmayacağız.

Eğer uğursuz bir uyarı görüyoruz çınlama ile çalışırsak (see it live):

uyarı: '' kendi başlatma kullanıldığında içinde başlatılmamış [-Wuninitialized] . foo değişkeni

producing and indeterminate value from an uninitialized automatic variable is undefined behavior beri geçerli bir uyarıdır ama bu durumda sadece bir referans bağlayıcı ve belirsiz bir değer üretmez ve geçerli olan yapıcısı içinde değişkenin adresi alıyor. Diğer taraftan, aşağıdaki başlatma kendinden örnek:

int x = x ;

çağırmak tanımsız davranış.

Active issue 453: References may only bind to “valid” objects de ilgili görünüyor, ama hala açık ama ilk önerilen dil kusur 363 raporu ile tutarlıdır.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Charles Nesson

    Charles Ness

    27 NİSAN 2006
  • Techmoan

    Techmoan

    31 Mayıs 2009
  • THE RED DRAGON

    THE RED DRAG

    6 ŞUBAT 2009