Önemsiz varsayılan yapıcı herhangi bir işlem yapmazsa neden malloc kullanarak önemsiz olarak oluşturulabilir nesneler oluşturamıyoruz?


14

Önemsiz varsayılan yapıcı hakkında cppreference alıntı yapılan aşağıdaki paragraf anlamakta zorlanıyorum . Stackoverflow aradım ama hala net bir cevap alamadım. Lütfen yardım edin.

Önemsiz bir varsayılan kurucu, hiçbir eylem gerçekleştirmeyen bir kurucudur. C dili ile uyumlu tüm veri türleri (POD türleri) önemsiz şekilde varsayılan olarak yapılandırılabilir. Bununla birlikte, C'den farklı olarak, önemsiz varsayılan kurucuları olan nesneler, std :: malloc ile ayrılan bellek gibi uygun şekilde hizalanmış depolamanın yeniden yorumlanmasıyla oluşturulamaz: yeni bir nesneyi resmen tanıtmak ve potansiyel tanımlanmamış davranışlardan kaçınmak için placement-new gereklidir.

Özellikle, önemsiz varsayılan yapıcı hiçbir şey yapmazsa, neden depolamayı yeniden yorumlayamaz ve verilen türde bir nesne olduğunu iddia edemeyiz? Bunun yol açabileceği potansiyel tanımlanmamış davranış için bazı örnekler verebilir misiniz ?


Derleyicinin en önemli işi kaynak kodlarını derlemek değil, geçersiz kodları reddetmektir. Malloc () kullandığınızda bunu yapamazsınız.
Hans Passant

6
Nedeni çok basit. Programcının çılgın şeyler yapması için ne kadar az fırsat olursa, derleyicinin çılgın şeyler yapması için o kadar çok fırsat vardır (agresif optimizasyonlar).
n. 'zamirler' m.

1
Benzer nedenlerden ötürü sadece yapamazsın *reinterpret_cast<float*>(&someNonFloatObject) = 0.1f;. C ++, soyut makinede belirtilen bir nesne ve nesne ömrü kavramına sahiptir ve depolamadan bir nesne oluşturmak için CPU talimatı olmaması, soyut makinede hiçbir fark olmadığı anlamına gelmez.
Max Langhof

1
@HansPassant Tüm kodu reddeden bir derleyici tüm geçersiz kodu reddeder. Her neyse, UB olan programları reddetmek copiler'ın işi değildir.
n. 'zamirler' m.

Yanıtlar:


7

P0593R5 bu örneği verir:

struct X { int a, b; };
X *make_x() {
  X *p = (X*)malloc(sizeof(struct X));
  p->a = 1;
  p->b = 2;
  return p;
}

ve açıklar:

Bir C ++ derleyicisi ile derlendiğinde, bu kod tanımsız bir davranışa sahiptir, çünkü p-> bir X nesnesinin int alt nesnesine yazmaya çalışır ve bu program hiçbir zaman bir X nesnesi veya int alt nesnesi oluşturmaz.

[İntro.object] p1 başına,

Nesne, bir birleşimin etkin üyesini dolaylı olarak değiştirirken veya geçici bir nesne oluşturulduğunda tanım, yeni ifade ile oluşturulur.

... ve bu program bunların hiçbirini yapmadı.

Uygulamada bu işe yarar ve UB durumu standartta her şeyden çok bir kusur olarak kabul edilir. Makalenin tüm amacı, bu sorunu ve benzer vakaları başka şeyleri bozmadan çözmenin bir yolunu sunmaktır.


1

"Saflık" nedeni için.

Alternatif ve gerçek durum kotası , her depolama bölgesinin aynı anda o depoya uyan tüm nesneleri içermesidir. Bazı komite üyeleri statükodan rahatsız ve birçok insan aynı yerde (sanal, başlatılmamış bir durumda) sonsuz sayıda nesneye sahip olma fikrinden korkuyordu.

Hiç kimse, bir depolama bölgesinde sonsuz sayıda nesneye sahip olmakla bir mantık sorunu gösteremedi.

Standartların farklı bölümleri birbiriyle çeliştikleri için komite üyeleri standardın en kötü kısımlarından birini ciddiye almaya karar verdiler.

Ayrıca, standardın bu kısmını gerçekten ciddiye alırsanız, dizgi değişmezlerini kullanmaya kesinlikle izin verilmez.


dize değişmezleri kullanılmasına kesinlikle izin verilmez . type_infoNesneler hakkında benzer CWG sorunu var . 'Bout string literals' bildirdiniz mi?
Dil Avukatı
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.