C ++ 03 throw () belirleyicisi arasındaki fark C ++ 11 noexcept


100

Herhangi arasındaki fark var mı throw()ve noexceptsırasıyla çalışma zamanı ve derleme zamanında, kontrol ediliyor dışındaki?

Bu Wikipedia C ++ 11 makalesi , C ++ 03 atma tanımlayıcılarının kullanımdan kaldırıldığını önermektedir.
Neden öyleyse, noexcepttüm bunları derleme zamanında kapsayacak kadar yetenekli mi?

[Not: Bu soruyu kontrol ettim ve bu makaleyi , ancak kullanımdan kaldırmanın sağlam nedenini belirleyemedim.]


7
Bu güzel makaleye görenoexcept çalışma zamanı kontrolleri de gerekebilir. Aralarındaki temel fark, noexceptnedenleri std::terminatekırarken thrownedenleri kırmaktır std::unexpected. Ayrıca bu durumlarda biraz farklı bir yığın çözme davranışı.
Fiktik

Diğerlerinde "çalışma zamanı" işaretli olan bazı istisna belirtimleriyle kontrol edilen "derleme zamanı" hiçbir şey yoktur. Bu sadece C ++ istisna özelliklerinin rakiplerinin yarattığı bir efsanedir.
wonderguy

Yanıtlar:


129

İstisna belirleyicileri kullanımdan kaldırıldı çünkü istisna belirleyicileri genellikle berbat bir fikirdir . noexceptbir istisna tanımlayıcının makul derecede kullanışlı bir kullanımı olduğu için eklendi: bir işlevin ne zaman olmayacağını bilmek bir özel durum. Böylece ikili bir seçim haline gelir: fırlatacak fonksiyonlar ve fırlatmayacak fonksiyonlar.

noexceptdaha güçlü throw()olduğu noexceptiçin hariç tüm atış belirleyicilerini kaldırmak yerine eklendi . noexceptderleme zamanının bir boolean'a dönüştüğü bir parametreye sahip olabilir. Boole değeri doğruysa, noexceptçubuklar. Boolean yanlışsa, noexceptyapışmaz ve işlev atabilir.

Böylece şuna benzer bir şey yapabilirsiniz:

struct<typename T>
{
  void CreateOtherClass() { T t{}; }
};

Does CreateOtherClassatmak istisnalar? Bu takdirde, belki Tbireyin varsayılan yapıcı can. Nasıl söyleriz Bunun gibi:

struct<typename T>
{
  void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; }
};

Böylece, CreateOtherClass()belirtilen türün varsayılan yapıcısı atarsa ​​atar. Bu, istisna tanımlayıcılarla ilgili en büyük sorunlardan birini düzeltir: çağrı yığınını yayamama.

Bunu ile yapamazsınız throw().


+1 Yine de benim için faydalı cevap. Hala neden kullanmak istediğimi söyleyen bir cevap arıyorum noexcept. Tanımlayıcıyı asla kullanmadım throw()ve noexceptgerçekten herhangi bir fayda sağlayıp sağlamadığını belirlemeye çalışıyorum (derleyici tarafından kontrol edilen belgeler dışında).
hmjd


1
@NicolBolas katılıyor. ancak noexcept bir garanti değilse, derleyici bir işlevin bir yıkıcıya atıp atmayacağını kontrol edebilir. Böylelikle bir programcıyı bir fonksiyonun istisnasız olup olmadığı konusunda uyarabilmek.
Alex

2
@NicolBolas çalışma zamanı çağırır std::terminate. hangi YOL KÖTÜ ! kod, işaretlenmiş işlevlere sahip sürümlere sızabilir noexcept ve çalışma zamanında (müşteri sitelerinde) ihlaller tespit edilir. Derleyicinin ilk etapta istisnalar atmayan kod üretmeyi garanti ettiğini kastettim .
Alex

2
@NicolBolas: Kayda değer bir fark daha. Bir işlev işaretlenirse throws(), bir istisna atılırsa, yığın o işlevin kapsamına kadar açılmalıdır (böylece işlevdeki tüm otomatik değişkenler yok edilir), bu noktada terminate()(aracılığıyla unexpected()) çağrılır . Bir işlev işaretlenirse noexcept, bir istisna atılırsa, sonlandırma çağrılır (yığının çözülmesi, uygulama tanımlı ayrıntıdır).
Martin York

33

noexcept derleme zamanında kontrol edilmez.

Bir uygulama, yalnızca çalıştırıldığında içeren işlevin izin vermediği bir istisna attığı veya atabileceği için bir ifadeyi reddetmemelidir.

Bir işlev bildirildiğinde noexceptveya throw()bir istisna atmaya teşebbüs ettiğinde , tek fark, bir çağrının terminateve diğer çağrıların unexpectedve ikinci istisna işleme tarzının etkin bir şekilde kullanımdan kaldırılmış olmasıdır.


Ancak bir sanal işlevde throw()/ varsa noexcept, derleme zamanı denetimi, bir geçersiz kılanın da sahip olduğundan emin olun.
curiousguy

2

std::unexpected() dinamik bir özel durum belirtimi ihlal edildiğinde C ++ çalışma zamanı tarafından çağrılır: özel durum belirtimi bu türdeki istisnaları yasaklayan bir işlevden bir istisna atılır.

std::unexpected() doğrudan programdan da çağrılabilir.

Her iki durumda da, std::unexpectedşu anda kurulu olanı çağırır std::unexpected_handler. Varsayılan std::unexpected_handleraramalar std::terminate.

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.