Gerçekten ne zaman istisnasız kullanmalıyım?


507

noexceptAnahtar kelime uygun birçok fonksiyon imzaları uygulanabilir, ama ben pratikte bunu kullanmayı düşünmelisiniz olarak emin değilim. Şimdiye kadar okuduğum şeye dayanarak, son dakika eklemesi, noexcepthamle yapıcıları fırlattığında ortaya çıkan bazı önemli sorunları ele alıyor gibi görünüyor. Ancak, noexceptilk etapta daha fazla bilgi edinmemi sağlayan bazı pratik sorulara hala tatmin edici cevaplar veremiyorum .

  1. Asla atmayacağını bildiğim, ancak derleyicinin kendi başına belirleyemediği birçok işlev örneği var. Tüm bu durumlardanoexcept işlev beyanına eklemem gerekir mi?

    Her işlev bildiriminden noexceptsonra eklemem gerekip gerekmediğini düşünmek, programcı verimliliğini büyük ölçüde azaltacaktır (ve açıkçası, kıçta bir ağrı olacaktır). Hangi durumlarda kullanımı konusunda daha dikkatli olmalıyım ve hangi durumlarda zımni olarak kurtulabilirim ?noexceptnoexcept(false)

  2. Ne zaman kullandıktan sonra gerçekçi bir performans artışı gözlemlemeyi bekleyebilirim noexcept? Özellikle, bir C ++ derleyicisinin eklenmesinden sonra daha iyi makine kodu üretebildiği bir kod örneği verin noexcept.

    Şahsen, noexceptderleyiciye belirli optimizasyonların güvenli bir şekilde uygulanması için sağlanan özgürlüğün artması nedeniyle önem veriyorum . Modern derleyiciler noexceptbu şekilde faydalanıyor mu? Değilse, bazılarının bunu yakın gelecekte yapmasını bekleyebilir miyim?


40
Kullanılmayan move_if_nothrow(veya whatchamacallit) kod, istisnai bir taşıma kaseti varsa performansta bir iyileşme görecektir.
R. Martinho Fernandes


5
Öyle move_if_noexcept.
Nikos

Yanıtlar:


180

Bunun için "en iyi uygulamalar" cevabını vermek için henüz çok erken olduğunu düşünüyorum çünkü uygulamada kullanmak için yeterli zaman yoktu. Bu, atış belirteçleri çıktıktan hemen sonra sorulursa, cevaplar şimdiden çok farklı olurdu.

noexceptHer işlev bildiriminden sonra eklemem gerekip gerekmediğini düşünmek, programcı verimliliğini büyük ölçüde azaltacaktır (ve açıkçası, bir acı olacaktır).

O zaman, fonksiyonun asla atmayacağı belli olduğunda kullanın.

Ne zaman kullandıktan sonra gerçekçi bir performans artışı gözlemlemeyi bekleyebilirim noexcept? [...] Şahsen, noexceptderleyiciye belirli optimizasyonların güvenli bir şekilde uygulanması için sağlanan özgürlüğün artması nedeniyle önem veriyorum .

En büyük optimizasyon kazançları, kontrol noexceptve aşırı yükleme olasılığı nedeniyle derleyici değil, kullanıcı optimizasyonlarından kaynaklanıyor gibi görünüyor . Çoğu derleyici, eğer atmazsanız istisna işleme yöntemini cezalandırmaz, bu nedenle kodunuzun makine kodu düzeyinde çok (veya herhangi bir şey) değişeceğinden şüpheleniyorum, ancak belki de ikili boyutu kaldırarak işlem kodu.

Kullanılması noexceptdört büyük yılında (zaten konum olarak kurucular, atama, değil Yıkıcıların noexceptolarak muhtemelen en iyi gelişmeleri beraberinde getirecektir) noexceptdenetimlerinde olduğu gibi şablon kodunda 'ortak' olan stdkonteynerler. Örneğin, std::vectorişaretlenmedikçe sınıfınızın hareketini kullanmayacaktır noexcept(veya derleyici başka türlü çıkaramazsa ).


6
Bence std::terminatehile hala Sıfır Maliyet modeline uyuyor. Olduğunu, sadece çok içinde talimatların aralığı olur noexceptfonksiyonları çağırmak eşleştirilmiş std::terminateeğer throwyerine yığın unwinder kullanılır. Bu yüzden düzenli istisna takibi daha fazla yük olduğundan şüpheliyim.
Matthieu

4
@Klaim Şuna bakın: stackoverflow.com/a/10128180/964135 Aslında sadece fırlatma olmamalı, ancak bunu noexceptgaranti ediyor.
Pubby

3
"Eğer bir noexceptfonksiyon fırlatılırsa std::terminate, az miktarda ek yük içerecekmiş gibi görünür" ... Hayır, bu, istisna görevlisinin yakalayıp sonradan kurtarması gereken böyle bir işlev için istisna tabloları üretmeyerek uygulanmalıdır.
Potatoswatter

8
@Pubby C ++ istisna işleme, potansiyel olarak çağrı sitesi adreslerini işleyici giriş noktalarına atanan atlama tabloları dışında ek yük olmadan yapılır. Bu tabloları kaldırmak, kural dışı durum işlemeyi tamamen kaldırmak kadar yakındır. Tek fark yürütülebilir dosya boyutudur. Muhtemelen bir şeyden bahsetmeye değmez.
Potatoswatter

26
"Peki o zaman fonksiyonun asla atmayacağı belli olduğunda kullanın." Katılmıyorum. noexceptfonksiyonun arayüzünün bir parçasıdır ; yalnızca geçerli uygulamanızın atmadığı için eklememelisiniz . Bu sorunun doğru cevabından emin değilim, ancak bugünkü fonksiyonunuzun nasıl davrandığının onunla hiçbir ilgisi olmadığından eminim ...
Nemo

133

Bu günleri tekrarlamaya devam ederken: önce anlambilim .

Ekleme noexcept, noexcept(true)ve noexcept(false)her şeyden önce anlambilim ile ilgilidir. Sadece tesadüfen bir dizi olası optimizasyonu koşullandırır.

Bir programcı okuma kodu olarak, varlığı noexceptaşağıdakine benzer const: ne olabilir veya olmayabilir ne daha iyi grok yardımcı olur. Bu nedenle, fonksiyonun atıp atmayacağını bilip bilmediğinizi düşünmek için biraz zaman ayırmaya değer. Bir hatırlatma için her türlü dinamik bellek tahsisi yapılabilir.


Tamam, şimdi olası optimizasyonlara geçelim.

En belirgin optimizasyonlar aslında kütüphanelerde gerçekleştirilir. C ++ 11, bir işlevin olup olmadığını bilmenizi sağlayan bir dizi özellik sağlar noexceptve Standart Kütüphane uygulamasının kendisi noexcept, mümkünse, manipüle ettikleri kullanıcı tanımlı nesneler üzerindeki işlemleri desteklemek için bu özellikleri kullanır . Bu gibi hareket semantik .

Çünkü derleyici yalnızca, veri işleme istisnadan yağ (belki) biraz tıraş olabilir sahiptir dikkate Yalan olabileceği gerçeğini almaya. İşaretlenmiş bir fonksiyon varsa noexceptatışı yapar, sonra da std::terminatedenir.

Bu semantik iki nedenden dolayı seçildi:

  • noexceptbağımlılıklar zaten kullanmıyor olsa bile hemen faydalanabilirsiniz (geriye dönük uyumluluk)
  • noexceptteorik olarak atılabilen ancak verilen argümanlar için beklenmeyen işlevleri çağırırken belirtilmesine izin vermek

2
Belki de naifim, ama sadece noexceptişlevleri çağıran bir fonksiyonun özel bir şey yapması gerekmeyeceğini hayal ederdim, çünkü ortaya çıkabilecek herhangi bir istisna terminatebu seviyeye gelmeden önce tetiklenir . Bu, bir bad_allocistisna ile başa çıkmak ve yaymaktan çok farklıdır .

8
Evet, noexcept'i önerdiğiniz şekilde tanımlamak mümkündür, ancak bu gerçekten kullanılamaz bir özellik olacaktır. Belirli koşullar yerine getirilmezse birçok işlev fırlayabilir ve koşulların karşılandığını bilseniz bile bunları çağıramazsınız. Örneğin, std :: invalid_argument atabilecek herhangi bir işlev.
tr3w

3
@MatthieuM. Cevap için biraz geç ama yine de. Noexcept olarak işaretlenen işlevler atabilecek diğer işlevleri çağırabilir, söz veriyorum, bu işlev bir istisna yaymayacaktır, yani sadece istisnayı kendileri ele almak zorundadırlar!
Honf

4
Bu cevabı uzun zaman önce onayladım, ancak biraz daha okudum ve düşündüm, bir yorumum / sorum var. "Hareket semantiği" şimdiye kadar kimsenin açıkça yararlı / iyi bir fikir verdiğini gördüğüm tek örnek noexcept. Hareket etmeyi, hareket atamayı ve takas etmeyi düşünmeye başladım sadece durumlar ... Başkalarını biliyor musunuz?
Nemo

5
@Nemo: Standart kütüphanede muhtemelen tek kitaptır, ancak başka bir yerde tekrar kullanılabilecek bir prensip sergilemektedir. Bir taşıma işlemi, geçici olarak bir durumu "limbo" ya koyan bir işlemdir ve ancak noexceptbiri daha sonra erişilebilecek bir veri parçası üzerinde güvenle kullanabilir. Bu fikrin başka bir yerde kullanıldığını görebiliyordum, ancak Standart kütüphane C ++ 'da oldukça incedir ve sadece bence elemanların kopyalarını optimize etmek için kullanılır.
Matthieu

77

Bu aslında derleyicideki optimize edici için (potansiyel olarak) büyük bir fark yaratır. Derleyiciler aslında bir işlev tanımından sonra boş throw () deyimi ve uygun uzantılar aracılığıyla yıllardır bu özelliğe sahiptir. Modern derleyicilerin daha iyi kod üretmek için bu bilgiden faydalandığını garanti edebilirim.

Derleyicideki hemen hemen her optimizasyon, neyin yasal olduğunu anlamak için bir fonksiyonun "akış grafiği" adı verilen bir şey kullanır. Bir akış grafiği, genellikle fonksiyonun "blokları" olarak adlandırılanlardan (tek bir girişi ve tek bir çıkışı olan kod alanları) ve akışın nereye atlayabileceğini gösteren bloklar arasındaki kenarlardan oluşur. Noexcept akış grafiğini değiştirir.

Belirli bir örnek istediniz. Bu kodu düşünün:

void foo(int x) {
    try {
        bar();
        x = 5;
        // Other stuff which doesn't modify x, but might throw
    } catch(...) {
        // Don't modify x
    }

    baz(x); // Or other statement using x
}

Bu işlevin akış grafiği, bar etiketliysenoexcept (yürütmenin sonu ile barcatch deyimi arasında atlaması mümkün değildir ). Olarak etiketlendiğinde noexcept, derleyici baz fonksiyonu sırasında x değerinin 5 olduğundan emin olur - x = 5 bloğunun kenar bar()(catch) ifadesinden kenar olmadan baz (x) bloğuna "hükmettiği" söylenir .

Daha verimli kod üretmek için "sürekli yayılma" adı verilen bir şey yapabilir. Burada baz işaretlenirse, x kullanan ifadeler de sabitler içerebilir ve daha sonra çalışma zamanı değerlendirmesi olarak kullanılanlar derleme zamanı değerlendirmesine vb. Dönüştürülebilir.

Her neyse, kısa cevap: noexceptderleyicinin daha sıkı bir akış grafiği oluşturmasına izin verir ve akış grafiği, her türlü ortak derleyici optimizasyonu hakkında düşünmek için kullanılır. Bir derleyici için, bu türdeki kullanıcı ek açıklamaları harika. Derleyici bu şeyleri anlamaya çalışacaktır, ancak genellikle (söz konusu işlev, derleyici tarafından görülemeyen başka bir nesne dosyasında olabilir veya görünür olmayan bir işlevi geçici olarak kullanabilir) veya olduğunda, farkında bile olmadığınız atılabilecek bazı önemsiz istisnalar, bu yüzden bunu dolaylı olarak etiketleyemez noexcept(örneğin bellek ayırmak bad_alloc atabilir).


3
Bu aslında pratikte bir fark yaratıyor mu? Örnek konudur çünkü daha önce hiçbir şeyx = 5 fırlatamaz. tryBloğun bu kısmı herhangi bir amaca hizmet ettiyse , mantık geçerli olmazdı.
Potatoswatter

7
Deneme / yakalama blokları içeren işlevleri optimize etmede gerçek bir fark yarattığını söyleyebilirim. Verilmiş olmasına rağmen verdiğim örnek kapsamlı değil. Daha büyük nokta, noexcept'in (önceki atma () ifadesi gibi), derlemenin daha sonra yaptığı birçok optimizasyonun temel bir parçası olan daha küçük bir akış grafiği (daha az kenar, daha az blok) oluşturmasına yardımcı olmasıdır.
Terry Mahaffey

Derleyici, kodun istisna atabileceğini nasıl anlayabilir? Diziye erişim ve diziye erişim olası bir istisna olarak kabul ediliyor mu?
Tomas Kubes

3
@ qub1n Derleyici işlevin gövdesini görebiliyorsa, açık throwifadeler veya newbunun gibi başka şeyler arayabilir. Derleyici vücudu göremezse, varlığına veya yokluğuna güvenmelidir noexcept. Düz dizi erişimi genellikle istisnalar oluşturmaz (C ++ sınır denetimi içermez), bu nedenle hayır, dizi erişimi tek başına derleyicinin bir işlevin istisnalar attığını düşünmesine neden olmaz. (
Sınır dışı

@cdhowie "noexcept'in varlığına veya yokluğuna güvenmelidir " veya throw()noexex öncesi C ++ 'da varlığı
curiousguy

57

noexceptbazı işlemlerin performansını önemli ölçüde artırabilir. Bu, derleyici tarafından makine kodu oluşturma düzeyinde gerçekleşmez, ancak en etkili algoritmayı seçerek: diğerlerinin belirttiği gibi, bu seçimi işlevi kullanarak yaparsınız std::move_if_noexcept. Örneğin, std::vector(örneğin, dediğimizde reserve) büyümesi güçlü bir istisna güvenliği garantisi sağlamalıdır. Eğer onun Thareket yapıcısının fırlatmadığını bilirse , sadece her elemanı hareket ettirebilir. Aksi takdirde tüm kopyaları kopyalamalıdır T. Bu ayrıntılı olarak tarif edilmiştir bu yazı .


4
Zeyilname: Bu, hareket oluşturucuları tanımladığınızda veya hareket atama işleçlerini noexceptbunlara eklediğinizde (varsa) anlamına gelir! Örtük olarak tanımlanmış taşıma üye işlevleri noexceptbunlara otomatik olarak eklenmiştir (varsa).
mucaho

33

Kullandıktan sonra performans artışı gözlemlemek dışında ne zaman gerçekçi olabilirim noexcept? Özellikle, bir C ++ derleyicisinin noexcept eklendikten sonra daha iyi makine kodu üretebildiği bir kod örneği verin.

Um, asla? Asla bir zaman değil mi? Asla.

noexceptiçindir derleyici aynı şekilde performans optimizasyonları constderleyici performans optimizasyonları içindir. Yani, neredeyse asla.

noexceptöncelikle bir işlevin bir istisna atabilip getiremeyeceğini derleme zamanında "sizin" algılamanıza izin vermek için kullanılır. Unutmayın: Çoğu derleyici, gerçekten bir şey atmadıkça istisnalar için özel kod yayınlamaz. Yani noexceptderleyiciye bir işlevi vermek kadar çok optimize etmek hakkında ipuçları vermek meselesi değil size bir işlevi kullanma hakkında ipuçları.

Gibi Şablonlar move_if_noexcepthareket yapıcısı ile tanımlanması durumunda algılar noexceptve bir döner const&bir yerine&& türün . Bunu yapmak çok güvenliyse hareket etmenin bir yolu.

Genel olarak, noexceptgerçekten yararlı olacağını düşündüğünüzde kullanmalısınız . Bazı kodlar farklı yollar alırsais_nothrow_constructibleBu tür için doğruysa . Bunu yapacak bir kod kullanıyorsanız,noexcept uygun kurucular .

Kısacası: hareket yapıcılar ve benzer yapılar için kullanın, ama onunla çıldırmak zorunda hissetmeyin.


13
Kesinlikle, move_if_noexceptbir kopyasını döndürmez, bir rvalue referansı yerine bir const lvalue referansı döndürür. Genel olarak bu, arayan kişinin taşıma yerine bir kopya oluşturmasına neden olur, ancak move_if_noexceptkopyayı yapmaz. Aksi takdirde, büyük açıklama.
Jonathan Wakely

12
+1 Jonathan. Örneğin, bir vektörü yeniden boyutlandırmak nesneleri taşıma yapıcısı ise kopyalamak yerine hareket ettirir noexcept. Böylece "asla" doğru değil.
mfontanini

4
Ben derleyici, demek olur bu durumda daha iyi kod oluşturmak. OP, derleyicinin daha optimize edilmiş bir uygulama üretebileceği bir örnek ister. Durum böyle görünüyor ( derleyici optimizasyonu olmasa bile ).
mfontanini

7
@mfontanini: Derleyici yalnızca daha iyi kod üretir çünkü derleyici farklı bir kod yolu derlemeye zorlanır . Bu sadece , çünkü çalışır std::vectorderlemek için derleyici zorlamak için yazılır farklı kod. Derleyicinin bir şey algılamasıyla ilgili değil; kullanıcı kodunun bir şeyi algılamasıyla ilgilidir.
Nicol Bolas

3
Mesele şu ki, cevabınızın başında alıntıda "derleyici optimizasyonu" bulamıyorum. @ChristianRau'nun dediği gibi, derleyici daha verimli bir kod üretir, bu optimizasyonun kaynağının ne olduğu önemli değildir. Sonuçta, derleyici olan daha verimli bir kod üreten, öyle değil mi? PS: Hiç derleyici optimizasyonu olduğunu söylemedim, hatta "Derleyici optimizasyonu değil" dedim.
mfontanini

22

In Bjarne 'ın sözleri ( C ++ Dili, 4. Baskı Programlama , sayfa 366):

Fesih kabul edilebilir bir yanıtsa, yakalanmamış bir istisna bunu bir terminate () çağrısına dönüştüğü için başaracaktır (§13.5.2.5). Ayrıca birnoexcept belirteç (§13.5.1.1) bu arzuyu açık hale getirebilir.

Başarılı hataya dayanıklı sistemler çok seviyelidir. Her seviye çok fazla bükülmeden olabildiğince çok hatayla başa çıkabilir ve gerisini daha yüksek seviyelere bırakır. İstisnalar bu görüşü destekler. Ayrıca, terminate()istisna işleme mekanizmasının kendisi bozuksa veya tam olarak kullanılmamışsa bir kaçış sağlayarak bu görüşü destekler , böylece istisnalar yakalanmaz. Benzer şekilde, noexceptkurtarmaya çalışmanın mümkün olmadığı hatalar için basit bir kaçış sağlar.

double compute(double x) noexcept;     {
    string s = "Courtney and Anya";
    vector<double> tmp(10);
    // ...
}

Vektör yapıcısı on katına kadar bellek alamaz ve a atar std::bad_alloc. Bu durumda program sona erer. std::terminate()Çağırmak suretiyle koşulsuz olarak sonlanır (§30.4.1.3). Yıkıcıları çağrı işlevlerinden çağırmaz. Uygulama tanımlıdır throwve noexcept(ile compute () için s) arasındaki kapsamlardan yıkıcıların çağrılıp çağrılmadığı. Program sona ermek üzeredir, bu yüzden zaten herhangi bir nesneye güvenmemeliyiz. Bir noexceptbelirteç ekleyerek , kodumuzun bir atımla başa çıkmak için yazılmadığını belirtiriz.


2
Bu alıntı için bir kaynağınız var mı?
Anton Golov

5
@AntonGolov "C ++ Programlama Dili, 4. Baskı" pg. 366
Rusty Shackleford

Bu, bana noexcepther seferinde gerçekten eklemem gerektiği gibi geliyor , ancak açıkça istisnalarla ilgilenmek istiyorum. Gerçek olalım, istisnaların çoğu o kadar imkansız ve / veya o kadar ölümcül ki kurtarmanın pek makul veya mümkün olmadığı. Alıntılanan örnekte, ayırma başarısız olursa, uygulama düzgün çalışmaya devam edemez.
Neonit

21
  1. Asla atmayacağını bildiğim, ancak derleyicinin bunu kendi başına belirleyemediği birçok işlev örneği var. Tüm bu durumlarda işlev beyanına istisna eklemem gerekir mi?

noexceptişlevler arayüzünün bir parçası olduğu için zor. Özellikle bir kitaplık yazıyorsanız, istemci kodunuz noexceptözelliğe bağlı olabilir . Varolan kodu kırabileceğiniz için daha sonra değiştirmek zor olabilir. Yalnızca uygulamanız tarafından kullanılan kodu uygularken bu daha az endişe verici olabilir.

Eğer atamadığınız bir fonksiyonunuz varsa, kendinize bunun kalmak isteyip istemeyeceğini noexceptveya gelecekteki uygulamaları kısıtlayacak mı diye sorun. Örneğin, kural dışı durumları (ör. Birim testleri için) atarak yasadışı argümanlarda hata denetimi yapmak isteyebilirsiniz veya kural dışı durum belirtimini değiştirebilecek diğer kitaplık koduna güvenebilirsiniz. Bu durumda, muhafazakar olmak ve atlamak daha güvenlidirnoexcept .

Öte yandan, fonksiyonun asla atmaması gerektiğinden eminseniz ve spesifikasyonun bir parçası olduğu doğruysa, beyan etmelisiniz noexcept. Ancak, derleyicinin noexceptuygulamanızın değişmesi durumunda ihlalleri tespit edemeyeceğini unutmayın.

  1. Hangi durumlar için noexcept kullanımı konusunda daha dikkatli olmalıyım ve hangi durumlar için zımni noexcept (false) ile kaçabilirim?

Konsantre olmanız gereken dört işlev sınıfı vardır, çünkü muhtemelen en büyük etkiye sahip olacaktır:

  1. taşıma işlemleri (atama işlecini taşıma ve yapıcıları taşıma)
  2. takas işlemleri
  3. bellek dağıtıcıları (operatör silme, operatör silme [])
  4. yıkıcılar ( noexcept(true)siz bunları yapmadığınız sürece bunlar dolaylı olarak noexcept(false))

Bu işlevler genellikle olmalıdır noexceptve büyük olasılıkla kütüphane uygulamaları bu noexceptözellikten yararlanabilir. Örneğin, std::vectorgüçlü istisna garantilerinden ödün vermeden fırlatma hareketi hareketlerini kullanabilir. Aksi takdirde, (C ++ 98'de olduğu gibi) kopyalama öğelerine geri dönmesi gerekecektir.

Bu tür bir optimizasyon algoritmik düzeydedir ve derleyici optimizasyonlarına dayanmaz. Özellikle öğelerin kopyalanması pahalıysa, önemli bir etkisi olabilir.

  1. NoExcept kullandıktan sonra ne zaman gerçekçi bir performans artışı gözlemlemeyi bekleyebilirim? Özellikle, bir C ++ derleyicisinin noexcept eklendikten sonra daha iyi makine kodu üretebildiği bir kod örneği verin.

noexceptİstisna belirtimine karşı olmayan avantajı veya throw()standardın, çözücüler yığın çözme konusunda daha fazla özgürlüğe izin vermesidir. throw()Durumda bile , derleyici yığını tamamen gevşetmelidir (ve nesne yapılarının tam tersi sırayla yapmalıdır).

Öte noexceptyandan, bunu yapmak gerekli değildir. Yığının açılmasına gerek yoktur (ancak derleyicinin bunu yapmasına izin verilir). Bu özgürlük, yığının her zaman çözülme yükünü azalttığı için daha fazla kod optimizasyonuna izin verir.

İstisna, yığın çözme ve performans ile ilgili soru , yığın çözme gerektiğinde ek yük hakkında daha fazla ayrıntıya girer.

Ayrıca Scott Meyers'ın "Effective Modern C ++", "Item 14: İstisnaları yaymayacakları sürece istisnasız işlevleri beyan etmeleri" kitabını tavsiye ederim.


Yine de, Java'da olduğu gibi C ++ 'da istisnalar uygulanmışsa throws, noexceptnegatif yerine anahtar kelime ile atılabilecek yöntemi işaretlerseniz çok daha mantıklı olur . C ++ tasarım seçeneklerinden bazılarını alamıyorum ...
doc

Onlar zaten adını almış noexceptçünkü adlandırdı throw. Basitçe söylemek gerekirse throw, neredeyse tasarlandıkları gibi kullanılabilirler , ancak tasarımı işe yaramazlardı, bu yüzden neredeyse işe yaramaz hale geldi - hatta zararlı. Ama şimdi onunla sıkışıp kaldık, çünkü onu kaldırmak çok az yararı olan bir değişiklik olacak. Yani noexcepttemelde throw_v2.
AnorZaken

Nasıl throwfaydalı değil?
curiousguy

@curiousguy "atmak" kendisini (istisnalar atmak için) kullanışlıdır, ancak bir istisna belirleyicisi olarak "atmak" kullanımdan kaldırılmıştır ve C ++ 17'de bile kaldırılmıştır. İstisna belirleyicilerinin yararlı olmama nedenleri için şu soruya bakın: stackoverflow.com/questions/88573/…
Philipp Claßen

1
@ PhilippClaßen throw()İstisna belirteci ile aynı garantiyi vermedi nothrowmi?
curiousguy

17

Asla atmayacağını bildiğim, ancak derleyicinin bunu kendi başına belirleyemediği birçok işlev örneği var. Tüm bu durumlarda işlev beyanına istisna eklemem gerekir mi?

"Asla atmayacaklarını biliyorum" derken, fonksiyonun uygulanmayacağını bildiğiniz fonksiyonun uygulamasını inceleyerek demek istersiniz. Bence bu yaklaşım içten dışa doğru.

Bir işlevin , işlevin tasarımının bir parçası olmak için istisnalar verip alamayacağını düşünmek daha iyidir : argüman listesi kadar önemli ve bir yöntemin bir mutatör olup olmadığı (... const). "Bu fonksiyon hiçbir zaman istisna oluşturmaz" ifadesinin uygulanması bir kısıtlamadır. Bunu atlamak, işlevin istisnalar atabileceği anlamına gelmez; bu, işlevin geçerli sürümünün ve gelecekteki tüm sürümlerin istisnalar atabileceği anlamına gelir . Uygulamayı zorlaştıran bir kısıtlamadır. Ancak bazı yöntemlerin pratik olarak yararlı olma kısıtlaması olmalıdır; en önemlisi, bu yüzden yıkıcılardan çağrılabilir, aynı zamanda güçlü istisna garantisi sağlayan yöntemlerde "geri alma" kodunun uygulanması için.


Bu en iyi cevap. Uygulamanızı sonsuza dek kısıtladığınızı söylemenin başka bir yolu olan (sans break-change) yönteminizin kullanıcılarına bir garanti veriyorsunuz . Aydınlatıcı perspektif için teşekkürler.
AnorZaken

Ayrıca ilgili bir Java sorusuna da bakın .
Raedwald
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.