Beni doğru dürüst sat


133

Öyleyse neden her zaman const'ı olabildiğince sık kullanmanız önerilir? Bana öyle geliyor ki const kullanmak C ++ 'da bir yardımdan daha fazla acı verici olabilir. Ama sonra tekrar, ben buna python perspektifinden geliyorum: eğer bir şeyin değiştirilmesini istemiyorsanız, onu değiştirmeyin. Bununla birlikte, işte birkaç soru:

  1. Görünüşe göre bir şeyi const olarak her işaretlediğimde, bir hata alıyorum ve başka bir işlevi de sabit olmak için bir yerde değiştirmem gerekiyor. O zaman bu, başka bir yerde başka bir işlevi değiştirmeme neden oluyor . Bu deneyimle daha da kolaylaşan bir şey mi?

  2. Const kullanmanın faydaları , sorunu telafi etmek için gerçekten yeterli mi? Bir nesneyi değiştirmeyi düşünmüyorsanız, neden onu değiştirmeyen bir kod yazmıyorsunuz?

Bu noktada, en çok doğruluk ve sürdürülebilirlik amaçları için const kullanmanın faydalarına odaklandığımı belirtmeliyim, ancak performans etkileri hakkında bir fikre sahip olmak da güzel.


1
8 yıl eski geçmişe dönük, ama .. Kodunuzu 100x hızlandırmaya ne dersiniz (bunu canlı izlediniz)?
lorro

1
Cevabımı burada kontrol edin (ilgili soru, aynı cevabı söyleyebilirim): stackoverflow.com/questions/42310477/… BTW: Seviyorumconst
Gines Hidalgo

Yanıtlar:


158

Bu, "sabit doğruluk" ile ilgili kesin makaledir: https://isocpp.org/wiki/faq/const-correctness .

Özetle, const kullanmak iyi bir uygulamadır çünkü ...

  1. Sizi yanlışlıkla değiştirilmesi amaçlanmayan değişkenleri değiştirmekten korur,
  2. Sizi yanlışlıkla değişken atamalar yapmaktan korur ve
  3. Derleyici bunu optimize edebilir. Örneğin, korunuyorsunuz

    if( x = y ) // whoops, meant if( x == y )

Aynı zamanda, derleyici daha verimli kod üretebilir çünkü değişkenin / fonksiyonun durumunun her zaman tam olarak ne olacağını bilir. Sıkı C ++ kodu yazıyorsanız, bu iyidir.

Sabit doğruluğu tutarlı bir şekilde kullanmanın zor olabileceği konusunda haklısınız, ancak son kod daha kısa ve programlanması daha güvenlidir. Çok fazla C ++ geliştirme yaptığınızda, bunun faydaları hızla ortaya çıkar.


Her zaman const değerlerinin serbestçe önbelleğe alınabileceğini ve böylece birçok eşzamanlılık sorununu önleyebileceğini veya hızı artırabileceğini varsaydım. Bu doğru mu?
Phil H

3
Elbette. constdeğişkenler , değişkenin tam amacını ve kullanımını bildiği için derleyicinin daha optimal kod üretebilmesi anlamında hızı artırabilir. Farkı fark edecek misin? Bu, başvurunuz üzerine tartışmalı. Eşzamanlılık söz konusu olduğunda, const değişkenleri salt okunurdur, yani değer her zaman aynı olacağı için bu değişkenler için özel kilitlere ihtiyaç yoktur.
Jordan Parmer

4
C ++ 11'den itibaren standart kitaplık aynı zamanda constiş parçacığı güvenli anlamına gelir ve kendi kodunuzu bu şekilde ele almak, olası çoklu iş parçacığı sorunlarını kontrol etmeyi kolaylaştırır ve API kullanıcılarınız için API garantileri sağlamanın kolay bir yoludur.
pmr

3
Benim için, const doğruluğunun en büyük katma değerlerinden biri, işaretçiler işlev tarafından hiçbir zaman değişime uğramayan verilere (yani yalnızca girdi) başvururken yalnızca işlev prototiplerine bakarak bilmenizdir.
cp.engr

1
Mantıksal ve fiziksel sabitlik olduğunu unutmayın . Değiştirilebilir olarak işaretlenmiş bulunan herhangi bir toplu nesne değişebilir, ancak bu şekilde işaretlenmesi, kapsayıcı nesnenin mantıksal sabitliği ile hiçbir ilgisi olmadığı anlamına gelir.
Adrian

128

İşte sabit doğruluğun sizi karşı koruyabileceği yaygın bir hataya sahip bir kod parçası:

void foo(const int DEFCON)
{
   if (DEFCON = 1)     //< FLAGGED AS COMPILER ERROR! WORLD SAVED!
   {
       fire_missiles();
   }
}

19
Yani, bazı kanlı salaklar C'deki atama operatörü olarak "=" seçtiği için const'ın gerekli olduğunu söylüyoruz. ;-)
Steve Jessop

37
Elbette, modern derleyicilerin çoğu koşullu atamalar konusunda uyarıyor ve hepimiz uyarıları hata bayrağı olarak ele alıyoruz, doğru: ->
Jack Bolding

7
Bu örnek üzerinde çok sert olmayın: Bu, bazı geliştiriciler tarafından bizi if (i == 0) yerine if (0 == i) kullanmaya ikna etmek için anlatılan aynı örnek. Sonunda, Doug'un kod kalıbı "if" ifadesinin dışında kullanılabilir. Önemli olan, const'ın faydalarından birini komik bir şekilde göstermesidir. + 1.
paercebal

2
Bazı derleyiciler (ve lint'ler) bu konuda uzun süredir uyarıda bulunuyorlar ve bu yazım hatasını yakalamak için const: codepad.org/Nnf5JUXV'den çok daha kullanışlıdır .

7
@Roger, yapıların temiz ve uyarıcı olmadığı bir dünyada yaşadığımızı varsayarsınız. Benim deneyimim, birçok kod uyarısının gürültü içinde kaybolmasıdır. Ayrıca, if ifadesinde atamalar yapan çok sayıda kod vardır ve birçoğu bunun geçerli, "iyi" bir stil olduğunu savunacaktır.
Doug T.

62

Görünüşe göre bir şeyi const olarak her işaretlediğimde, bir hata alıyorum ve başka bir işlevi de sabit olacak şekilde değiştirmem gerekiyor. O zaman bu, başka bir yerde başka bir işlevi değiştirmeme neden oluyor. Bu deneyimle daha da kolaylaşan bir şey mi?

Tecrübeye göre bu tam bir efsanedir. Sabit doğru olmayan sabit doğru kodla oturduğunda olur, elbette. Baştan itibaren const-true tasarlarsanız, bu ASLA bir sorun olmamalıdır. Bir şeyi const yaparsanız ve sonra başka bir şey derlemezse, derleyici size son derece önemli bir şey söylüyor demektir ve bunu düzgün bir şekilde düzeltmek için zaman ayırmalısınız .


7
Bu, const olmayan bir işlevi çağırmak üzere olan bir const işlevine sahip olduğum birçok hatayı önlememe yardımcı oldu çünkü altındaki verileri değiştirdiğini unuttum.
Ördek mölemeye

9
Çok az insan her zaman temiz kod tabanlarıyla başlar. Çoğu kodlama, alıntı yapılan yorumun oldukça doğru olduğu eski kod üzerinde bakımdır. Yeni yaprak işlevlerini yazarken const kullanıyorum, ancak yarım düzine veya bir düzine tanıdık olmayan kod çağrı düzeyi aracılığıyla bir şeyleri kovalamaya değip değmeyeceğini sorguluyorum.
Warren Dew

3
Bu benim deneyimime göre tamamen yanlış. İç içe geçmiş nokta türleri, bu tür şeyler için en büyük baş ağrısını oluşturur; burada tek bir türde birden çok sabit niceleyici olabilir.
Noldorin

4
"Eğer başlangıçtan itibaren const-doğru tasarlarsanız," başlangıçtan itibaren kaç kere sabit-doğruluğu zorlama lüksüne sahip olursunuz? Çoğumuz, durumun böyle olmadığı ve bunlar hakkında yapabileceğiniz çok az şeyin olduğu günlük bazda çok sayıda API ve kitaplıkla uğraşmak zorundayız. Bu yüzden OP'nin düşüncesine katılıyorum "Görünüşe göre bir şeyi sabit olarak her işaretlediğimde bir hata alıyorum a" ...
nyholku

@WarrenDew Bu geçişli bir argüman; orijinal yazarlar constdoğru kullanmış olsaydı (yani "baştan itibaren"), o zaman gerçekten de bir problem olmayacaktı, bu da tam olarak mesele!
Orbit'te Hafiflik Yarışları

31

Başlangıçta kodu yazarken size göre değil. Ne yaptığını görmek için sınıf veya arayüz içindeki yöntem bildirimine bakan bir başkası (veya birkaç ay sonra siz) için. Bir nesneyi değiştirmemek, bundan elde edilecek önemli bir bilgi parçasıdır.


1
Bu sadece doğru. Const, aynı zamanda, arayüzler vb. Aracılığıyla değişkenleri zorlamak için koruma olarak kullanılır.
Jordan Parmer

Öyle, ancak bunu disiplinli kodlama uygulamaları yoluyla uygulayabilirsiniz ve poster belirtiyor. Gerçek fayda, bunun API'ye yansıtılmasından gelir.
Antonio Haley

2
Kesinlikle. "Const int Value = 5" olması daha iyidir; "int ConstValue = 5;" olduğundan daha fazla. +1.
paercebal

6
Sabit doğruluğu eklemek için doğru zaman, başlangıçta API'yi yazdığınız zamandır. Aksi takdirde, onu güçlendirdiğinizde const zehirlenmesi ile sorun yaşarsınız (bu nedenle eski koda eklemek , yeni kodda yapmaktan tamamen farklı bir konudur ).
Donal Fellows

@DonalFellows bu daha sonra konsun demiyor. Daha sonra, const ile kodu okuduğunuzda faydaları elde edeceğinizi söylüyor
Caleth

27

Sabit'i titizlikle kullanırsanız, çoğu işlevde ne kadar az gerçek değişken olduğuna şaşıracaksınız. Genellikle bir döngü sayacından fazlası değildir. Kodunuz o noktaya ulaşıyorsa, içten bir sıcak his alırsınız ... derleme yoluyla doğrulama ... işlevsel programlama alanı yakında ... hemen hemen ona dokunabilirsiniz ...


1
C ++ 17 ve constexpr iyiliğinden beri derleme zaman birimi testleri yazıyorum ... daha da yaklaşıyorum ...
QBziZ

22

const, bir geliştirici olarak verdiğiniz ve zorlama konusunda derleyicinin yardımını aldığınız bir sözdür.

Sabit doğru olma nedenlerim:

  • Fonksiyonunuzun istemcilerine değişkeni veya nesneyi değiştirmeyeceğinizi bildirir.
  • Sabit referansına göre bağımsız değişkenleri kabul etmek, değere göre geçişin güvenliğiyle birlikte referansa göre geçirme verimliliği sağlar.
  • Arayüzlerinizi doğru olarak yazmak, istemcilerin bunları kullanmasını sağlayacaktır. Arayüzünüzü const olmayan referansları alacak şekilde yazarsanız, const kullanan istemcilerin sizinle çalışmak için sabitliği ortadan kaldırması gerekir. Arayüzünüz sabit olmayan char * 'ları kabul ediyorsa ve istemcileriniz std :: strings kullanıyorsa, bu özellikle can sıkıcıdır, çünkü onlardan yalnızca bir const char * alabilirsiniz.
  • Const kullanmak, derleyicinin sizi dürüst tutmasını sağlar, böylece değişmemesi gereken bir şeyi yanlışlıkla değiştirmezsiniz.

20

Benim felsefem, derleme zamanı kontrolleriyle birlikte nit-seçici bir dil kullanacaksanız, onu en iyi şekilde kullanmaktansa onu kullanabileceğinizdir. constne demek istediğinizi iletmenin derleyicinin zorladığı bir yoldur ... yorumlardan veya doxygen'in olmayacağı şeyden daha iyidir. Bedelini ödüyorsunuz, neden değeri türetmiyorsunuz?


20

C ++ 'ın const olmadan programlanması, emniyet kemeri takılmadan sürmek gibidir.

Arabaya her bastığınızda emniyet kemerini takmak çok acı ve 365 günün 364'ünü güvenle varacaksınız.

Tek fark, arabanızla başınız derde girdiğinde onu hemen hissedeceksiniz, oysa const olmadan programlamayla, yalnızca yanlışlıkla bir işlev argümanını bozduğunuzu bulmak için bu kazaya neyin neden olduğunu iki hafta boyunca aramanız gerekebilir. verimlilik için const olmayan bir referansla geçtiniz.


18

Gömülü programlama için, constglobal veri yapılarını bildirirken mantıklı bir şekilde kullanmak , sabit verilerin ROM'da veya önyükleme sırasında RAM'e kopyalanmadan flaşta bulunmasına neden olarak çok fazla RAM tasarrufu sağlayabilir.

Günlük programlamada constdikkatli kullanmak, dize değişmezlerini ve diğer sabit global verileri değiştirmeye çalıştıkları için çöken veya beklenmedik şekilde davranan programları yazmaktan kaçınmanıza yardımcı olur.

Büyük projelerde diğer programcılarla çalışırken, constdoğru şekilde kullanmak , diğer programcıların sizi kısıtlamasını önlemeye yardımcı olur.


13

constarkanızda "bir şeyleri değiştiren" kodu izole etmenize yardımcı olur. Yani, bir sınıfta, nesnenin durumunu değiştirmeyen tüm yöntemleri olarak işaretlersiniz const. Bunun anlamı şudur kiconst , o sınıfın örneklerinin artık constyöntem olmayan herhangi bir şeyi çağıramayacağı . Bu şekilde, yanlışlıkla nesnenizi değiştirebilecek işlevselliği çağırmanız engellenir.

Ayrıca, constaşırı yük mekanizmasının bir parçasıdır, bu nedenle aynı imzalara sahip, ancak biri olan constve olmayan iki yönteme sahip olabilirsiniz . İle bir constçağrılır constreferanslar, diğeri olmayan çağrılırconst referanslar.

Misal:

#include <iostream>

class HelloWorld {
    bool hw_called;

public:
    HelloWorld() : hw_called(false) {}

    void hw() const {
        std::cout << "Hello, world! (const)\n";
        // hw_called = true;  <-- not allowed
    }

    void hw() {
        std::cout << "Hello, world! (non-const)\n";
        hw_called = true;
    }
};

int
main()
{
    HelloWorld hw;
    HelloWorld* phw1(&hw);
    HelloWorld const* phw2(&hw);

    hw.hw();    // calls non-const version
    phw1->hw(); // calls non-const version
    phw2->hw(); // calls const version
    return 0;
}

13

const doğruluk, baştan beri gerçekten olması gereken şeylerden biridir. Bulduğunuz gibi, daha sonra eklemek büyük bir acı, özellikle de eklediğiniz yeni işlevler ile zaten var olan eski sabit olmayan işlevler arasında çok fazla bağımlılık olduğunda.

Yazdığım birçok kodda, gerçekten çabaya değdi çünkü kompozisyonu çok fazla kullanma eğilimindeyiz:

class A { ... }
class B { A m_a; const A& getA() const { return m_a; } };

Eğer sabit doğruluğu olmasaydı, o zaman kimsenin B sınıfının iç durumunu arkanızdan değiştirmediğinden emin olmak için karmaşık nesneleri değerine göre geri döndürmeye başvurmanız gerekirdi.

Kısacası, const -rectness kendinizi yolun aşağısındaki acılardan kurtarmak için savunmaya yönelik bir programlama mekanizmasıdır.


7

Python'da bir değişkeniniz olduğunu varsayalım. Sen değil biliyorum gerekiyordu değiştirmemen . Ya yanlışlıkla yaparsan?

C ++, kendinizi ilk başta yapamamanız gereken bir şeyi yanlışlıkla yapmaktan korumanın bir yolunu sunar. Teknik olarak bunun üstesinden gelebilirsiniz, ancak kendinizi vurmak için fazladan iş yapmanız gerekir.


4

Burada c ++ 'da const hakkında güzel bir makale var . Oldukça basit bir fikir ama umarım biraz yardımcı olur.


3

"Const" anahtar sözcüğünü kullandığınızda, sınıflarınız için başka bir arayüz belirtmiş olursunuz. Tüm yöntemleri içeren bir arabirim ve yalnızca const yöntemlerini içeren bir arabirim vardır. Açıkçası bu, değiştirilmesini istemediğiniz bazı şeylere erişimi kısıtlamanıza izin verir.

Evet, zamanla kolaylaşıyor.


2

Ben teoride sabit doğruluğu severim. Bunu pratikte titizlikle uygulamaya çalıştığım her seferde, sonunda bozuldu ve const_cast kodu çirkin hale getirmeye başladı.

Belki sadece kullandığım tasarım desenleridir, ancak const her zaman çok geniş bir fırça olur.

Örneğin, basit bir veritabanı motoru hayal edin ... şema nesneleri, tabloları, alanları vb. İçerir. Bir kullanıcının, tablo şemasının kendisini değiştirmesine izin verilmediği anlamına gelen bir 'const Table' işaretçisine sahip olabilir ... tabloyla ilişkili veriler? Insert () yöntemi const olarak işaretlenmişse, veritabanını fiilen işlemek için dahili olarak sabitleri başka yere çevirmesi gerekir. Sabit olarak işaretlenmemişse, AddField yönteminin çağrılmasına karşı koruma sağlamaz.

Belki yanıt, sınıfı sabitlik gereksinimlerine göre bölmek olabilir, ancak bu, tasarımı getirdiği fayda için istediğimden daha karmaşık hale getirme eğilimindedir.


Örneğinizin bir const aşırı kullanımı durumu olduğunu düşünüyorum, ancak sabitliği kaldırmak için örnek değişkenlerine uygulanabilen değiştirilebilir değiştiriciyi unutmayın.
Zooba

2
Bir Insert () işlevi yanlış adlandırılmadığı sürece ne zaman const olarak işaretlenir? Bir şeyler eklemek genellikle onu eklediğiniz şeyi değiştirir, yani const değildir. Gerçekten istediğiniz şey bir TableWithConstSchema idi.
Greg Rogers

Başka bir sınıf ekleyebilirim, ancak API'yi tamamen sabit doğruluğu için gereksiz yere karmaşık hale getirmek istemiyorum.
Rob Walker

1

Derleyiciye aşağıdaki koda göre const ile de ipuçları verebilirsiniz.

#include <string>

void f(const std::string& s)
{

}
void x( std::string& x)
{
}
void main()
{
    f("blah");
    x("blah");   // won't compile...
}
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.