hata: silinen işlevin kullanılması


122

Bir arkadaşımın yazdığı bir C ++ kodu üzerinde çalışıyorum ve gcc4.6 ile derlerken daha önce hiç görmediğim şu hatayı alıyorum:

error: use of deleted function

GameFSM_<std::array<C, 2ul> >::hdealt::hdealt()’ is implicitly deleted because the default definition would be ill-formed:
uninitialized non-static const member const h_t FlopPokerGameFSM_<std::array<C, 2ul> >::hdealt::h

Düzenleme: Bu, yükseltme MSM: Boost Web Sayfası kullanan kodun bir kısmından gelir

Edit2: = delete()Kaynak kodunun hiçbir yerinde kullanılmaz.

Genel olarak konuşursak, bu hata ne anlama geliyor? Bu tür bir hata oluştuğunda ne aramalıyım?


4
ve derlediğiniz kod?
ColWhi

Daha çok hatanın ne anlama geldiğini merak ediyordum? Bunun için kodu da göndermem gerekir mi?
shuttle87

1
gcc.gnu.org/bugzilla/show_bug.cgi?id=47417 yardımcı olabilir, ayrıca boost kullanıyor musunuz?
ColWhi

@Sasquiha, evet boost MSM kullanıyorum.
shuttle87

20
Bu, bu tür bir hata için ilk Google eşleşmesi olarak ortaya çıktığından - buradaki durum bu değil, ancak bu tür bir hatanın en yaygın nedeni, bir sınıfa özel bir kurucu eklemenizden sonradır - sonuç olarak derleyici varsayılan kurucuyu oluşturmayı durdurur ve varsayılan kurucu aracılığıyla sınıfın bir örneği oluşturulursa, bu hata görünür. Varsayılan kurucuyu açıkça ekleyin.
SF.

Yanıtlar:


171

Hata mesajı, varsayılan kurucunun dolaylı olarak silindiğini açıkça belirtir . Hatta nedenini söylüyor: sınıf statik olmayan bir const değişkeni içeriyor ve bu değişken varsayılan ctor tarafından başlatılmayacak.

class X {
    const int x;
};

Olduğundan beri X::x, constbaşlatılması gerekir - ancak varsayılan bir ctor normalde onu başlatmaz (çünkü bir POD türü). Bu nedenle, varsayılan bir ctor elde etmek için kendiniz bir tane tanımlamanız gerekir (ve onu başlatmanız gerekir x). Referans olan bir üye ile aynı tür bir durumla karşılaşabilirsiniz:

class X { 
    whatever &x;
};

Muhtemelen her ikisinin de, esasen aynı nedenden ötürü, bir atama operatörünün örtük oluşturulmasını da devre dışı bırakacağını belirtmek gerekir. Örtük atama operatörü normalde üyelere göre atama yapar, ancak bir const üyesi veya referans üyesi ile bunu yapamaz çünkü üye atanamaz. Atamanın çalışması için kendi atama operatörünüzü yazmanız gerekir.

Bu nedenle bir constüye tipik olarak statik olmalıdır - bir atama yaptığınızda, yine de const üyesini atayamazsınız. Tipik bir durumda, tüm örnekleriniz aynı değere sahip olacaktır, bu nedenle hepsi aynı değere sahip bir değişkenin çok sayıda kopyasına sahip olmak yerine tek bir değişkene erişimi paylaşabilirler.

Elbette farklı değerlere sahip örnekler oluşturmak mümkündür - (örneğin) nesneyi oluşturduğunuzda bir değer iletirsiniz, böylece iki farklı nesne iki farklı değere sahip olabilir. Ancak, bunları takas etmek gibi bir şey yapmaya çalışırsanız, const üyesi takas edilmek yerine orijinal değerini koruyacaktır.


@Jeffry Coffin: Asıl hata mesajı bir düzenleme olarak gönderildi, Gönderilen ilk hata mesajı sadeceC++ error: use of deleted function
Alok

1
@Als: Üzgünüm, muhtemelen bunu bir hakaret veya bu emirle ilgili herhangi bir şey olarak niyet etmediğimi açıkça belirtmeliydim, sadece şu anda mevcut olan cevapların doğru olmadığını açıkça gösterdi.
Jerry Coffin

Sorun yok, kararlı olmak istemedim ... Cevabınız harika ve durumu en iyi açıklıyor. Benden +1 :)
Alok Save

Buradaki
sorunumda

2
@OllieFord: Duruma göre değişir. Örneğin, o alandaki bir değeri olan bir nesneyi o alanda farklı bir değere sahip olan diğerine atarsanız ne olur? Üzerine yazılması gerekiyorsa, sabit olamaz. Buna hiç izin verilmemesi gerekiyorsa, değer gerçekten türün bir parçası olabilir (örneğin, derleme zamanında biliniyorsa bir şablon parametresi).
Jerry Coffin

11

Olarak işaretlenmiş bir işlevi kullanıyorsunuz deleted.
Örneğin:

int doSomething( int ) = delete;

= Delete, C ++ 0x'in yeni bir özelliğidir. Bu, derleyicinin derlemeyi derhal durdurması ve kullanıcı böyle bir işlevi kullandıktan sonra "bu işlevin silinmesinden" şikayet etmesi gerektiği anlamına gelir.

Bu hatayı görürseniz, işlev bildirimini kontrol etmelisiniz =delete.

Daha C ++ 0x tanıtılan bu yeni özellik hakkında bilmek için, kontrol bu dışarı.


7
Merak ettiğim için, böyle bir şey ne zaman yardımcı olur?
Pepe

@Peter: örtük dönüşümleri önlemek için.
R. Martinho Fernandes

7
Aslında "örtülü olarak silindi çünkü ..." diyor , yukarıdaki örnek açık olacaktır.
Georg Fritzsche

@Peter R: Bir örnek gibi görünüyor: en.wikipedia.org/wiki/…
shuttle87

1
@Downvoter: Asıl hata mesajı bir düzenleme olarak gönderildi, Gönderilen ilk hata mesajı sadeceC++ error: use of deleted function
Alok

4

gcc 4.6, yazabileceğiniz silinmiş işlevlerin yeni bir özelliğini destekler

hdealt() = delete;

varsayılan kurucuyu devre dışı bırakmak için.

Burada derleyici, varsayılan bir kurucunun oluşturulamayacağını açıkça gördü ve =deletebunu sizin için yaptı.


2

Soyut bir sınıftan miras alırken ve alt sınıfımdaki tüm saf sanal yöntemleri uygulamadığımda bu hatayla karşılaştım.


1
Benzer şekilde, public virtual1. düzey temel sınıfın açıkça silinmiş bir varsayılan kurucuya sahip olduğu 2. düzey bir temel sınıftan türeterek de aynısını elde ettim . Kaldırma virtual, tüm yöntemleri uygulamak zorunda kalmadan sorunu çözdü.
Maitre Bart

1

Mevcut C ++ 0x standardında, varsayılan oluşturucuları silme sözdizimi ile açıkça devre dışı bırakabilirsiniz, örn.

MyClass() = delete;

Gcc 4.6, bu sözdizimini destekleyen ilk sürümdür, bu yüzden belki de sorun budur ...


Gcc 4.6 is the first version to support this syntaxSon zamanlarda gcc4.6 kullanmaya başladığımdan, bunu neden daha önce hiç görmediğimi açıklayacağını tahmin ediyorum.
shuttle87

2
Bu sözdizimini GCC 4.5 ile yıllardır kullanıyorum. Yani günler.
R. Martinho Fernandes

Ah, GCC 4.6'da bulunan yetki verilmiş ktorları düşünmüş olmalıyım.
jarmond

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.