C ++ işlev parametrelerinde değerlendirme sırası


93

Bu şekilde oluşan üç fonksiyonumuz (foo, bar ve baz) varsa ...

foo(bar(), baz())

C ++ standardının bazdan önce değerlendirileceğine dair herhangi bir garanti var mı?

Yanıtlar:


103

Hayır, böyle bir garanti yok. C ++ standardına göre belirtilmemiştir.

Bjarne Stroustrup, bazı nedenlerle bunu "C ++ Programlama Dili" 3. basım bölüm 6.2.2'de açıkça belirtmektedir:

İfade değerlendirme sırasına ilişkin kısıtlamaların olmaması durumunda daha iyi kod üretilebilir

Teknik olarak bu, aynı bölümün bir ifadenin bölümlerinin değerlendirme sırasının da belirtilmediğini söyleyen daha önceki bir kısmına atıfta bulunsa da, yani

int x = f(2) + g(3);   // unspecified whether f() or g() is called first

Bu cevabı 8 dakikada kabul edebilirim ... Sanırım biraz daha takılıyorum!
Clark Gaebel

5
Evet, ancak ifade değerlendirme sırası STRICT ise daha iyi kod YAZILABİLİR (= daha temiz), ki bu genellikle kod oluşturmadan çok daha önemlidir. Şu örneğe bakın: stackoverflow.com/questions/43612592/… İşte Stroustrup.
Bill Kotsias

1
Sipariş önemliyse sıralamayı kendiniz yapmakta özgürsünüz. Aksi takdirde, her zaman (nadiren?) Önemli olmayan bir şeyin her zaman bir bedeli olur. Bence kullanmadığınız şeyler için ödeme yapmama politikası, çoğu C ++ programcısının üzerinde hemfikir olduğu tek şeydir.
tweej

3
"Tanımlanmamış" yerine "belirtilmemiş davranış" olması gerekmez mi?
GoodDeeds

1
@ChrisDodd, "tanımlanmamış" ve "belirtilmemiş" kelimelerini kullandığı için kabul edilen bir cevaba olumsuz oy vermek bana kötü niyetli bilgiçlik gibi geliyor ... Bunun "tanımlanmamış davranış" olduğunu söylemedim, aksi takdirde "tanımsız" ve "belirtilmemiş" görünüyor eşanlamlı? Her halükarda, cevaba bir düzeltme önermek, bunu tartışmanın daha verimli bir yolu olabilirdi
Eli Bendersky

21

[5.2.2] İşlev çağrısından,

Argümanların değerlendirme sırası belirtilmemiştir. Bağımsız değişken ifade değerlendirmelerinin tüm yan etkileri, fonksiyon girilmeden önce yürürlüğe girer.

Bu nedenle, bar()daha önce çalışacağına dair bir garanti yoktur baz(), sadece bu bar()ve baz()daha önce çağrılacaktır foo.

Ayrıca [5] 'den şu ifadelere dikkat edin:

belirtildiği durumlar dışında [örneğin &&ve için özel kurallar ||], tek tek operatörlerin işlenenlerinin ve tek tek ifadelerin alt ifadelerinin değerlendirme sırası ve yan etkilerin meydana gelme sırası belirtilmemiştir.

böylece bile olmadığını soran olsaydı bar()önce çalışacaktır baz()içinde foo(bar() + baz()), sipariş hala belirsizdir.


4
[5.14] Mantıksal AND işlecinden bir "özel not" örneği: "Tersine &, &&soldan sağa değerlendirmeyi garanti eder: ikinci işlenen, birinci işlenen ise değerlendirilmez false."
Daniel Trebbien

20

Bar () ve baz () için belirli bir sıra yoktur - Standardın söylediği tek şey, foo () çağrılmadan önce ikisinin de değerlendirileceğidir. C ++ Standardından, bölüm 5.2.2 / 8:

Argümanların değerlendirme sırası belirtilmemiştir.


4
Foo () 'dan önce değerlendirilmeleri en azından biraz güven vericidir.
Bill Kotsias

1
@BillKotsias Standart ayrıca işlev çağrılarının üst üste binemeyeceğini söylüyor (yani bir uygulama 1. satırını bar, sonra 1. satırını baz, sonra 2. satırı barvb. Çalıştıramaz ) ki bu da güzel. :-)
melpomene


3

C ++ 11'de ilgili metin 8.3.6 Varsayılan bağımsız değişkenler / 9 (Vurgu benimki) içinde bulunabilir.

Varsayılan bağımsız değişkenler, işlev her çağrıldığında değerlendirilir. İşlev bağımsız değişkenlerinin değerlendirme sırası belirtilmemiş . Sonuç olarak, bir işlevin parametreleri, değerlendirilmeseler bile, varsayılan bir bağımsız değişkende kullanılmamalıdır.

Aynı söz, C ++ 14 standardı tarafından da kullanılır ve aynı bölümde bulunur .


0

Başkalarının daha önce de belirttiği gibi, standart bu özel senaryo için değerlendirme sırası konusunda herhangi bir rehberlik sağlamaz. Bu değerlendirme sırası daha sonra derleyiciye bırakılır ve derleyicinin bir garantisi olabilir.

C ++ standardının bir derleyiciye derleme / makine kodu oluşturma konusunda talimat vermek için gerçekten bir dil olduğunu hatırlamak önemlidir. Standart, denklemin yalnızca bir bölümüdür. Standardın belirsiz olduğu veya özel olarak tanımlandığı durumlarda, derleyiciye dönmeli ve C ++ talimatlarını gerçek makine diline nasıl çevirdiğini anlamalısınız.

Dolayısıyla, değerlendirme sıralaması bir gereklilikse veya en azından önemliyse ve çapraz derleyici uyumlu olmak bir gereklilik değilse, derleyicinizin nihayetinde bunu nasıl bir araya getireceğini araştırın, cevabınız nihai olarak orada olabilir. Derleyicinin gelecekte metodolojisini değiştirebileceğini unutmayın

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.