Okunabilirlik (referans) parametrelerinde const kullanmamak için geçerli bir neden midir?


24

Bazı fonksiyonlar yazarken aşağıdaki gibi parametrelerde const anahtar kelimesi buldum:

void MyClass::myFunction(const MyObject& obj,const string& s1,const string& s2,const string& s3){
}

genellikle bir satırı IDE veya vim'de 2 satıra bölmeye neden olur, bu yüzden parametrelerdeki tüm const anahtar kelimelerini kaldırmak istiyorum:

void MyClass::myFunction(MyObject& obj,string& s1,string& s2,string& s3){
} 

const kullanmamak için geçerli bir neden mi? Parametre nesnelerinin manuel olarak değişmemesi sağlanabilir mi?


110
"Hey, işlevsel olarak programımı değiştirmek istiyorum" daha okunaklı hale getirmek için kötü bir nedendir.
Pieter B

37
Program artık hiçbir şekilde okunaklı hale gelmiyor - Bir şeyin teslim edildiğini gördükten sonra const, fonksiyonda nasıl değiştirilebileceğini zahmet etmenize gerek kalmayacağına dair güçlü bir ipucunuz var.
saat

43
Okunabilirliği arttırmanın daha iyi bir yolu argüman sayısını azaltmaktır .
5gon12eder

15
'const' tartışmalı geliştirir okunabilirlik. Bu açıklama, objenin değişmeyebileceğini açıkça göstermektedir!
Charles

14
Okunabilirliğe yardımcı olacak şey, her virgülden sonra bir boşluk eklemek.
sam hocevar

Yanıtlar:


182

Okunabilirlik, beyaz boşluk kullanmayı öğrenmek için geçerli bir nedendir:

void MyClass::myFunction(
        const MyObject& obj,
        const string& s1,
        const string& s2,
        const string& s3
) {
    return;
}

Orada bulunan parametreler, fonksiyonun gövdesine karışmaz. Onları farklı bir satıra yerleştirerek, adını myFunctiondaha açıklayıcı bir şeyle değiştirdiğinizde yeniden konumlandırmanız gerekmez . Değişmediyse parametrelerin pozisyonunu değiştirmemek, kaynak kontrolü fark aracı kullanıcılarının takdir edeceği bir şeydir.

constbir anlamı var. Boşuna atmayın çünkü sadece alan ve fikirlerin dışındasınız. Okunabilirlik kraldır ama adına bir şeyleri parçalamak sadece vazgeçmektir.


6
"myFunction'ın adını değiştirdiğinizde bunları yeniden konumlandırmanız gerekmeyecek" - bu durumda yaklaşık olarak açılışla aynı hizada olacak şekilde konumlanmış gibi görünse de, bu durumda (yeniden konumlandırmanız gerekebilir sınıf + işlev adının uzunluğu yaklaşık 4 karakterden daha fazla değişirse, bunları kullanabilirsiniz. Öyleyse bunu yapmak istemiyorsanız, işlev adının uzunluğuna bağlı bir sayı değil, sabit sayıda girinti ekleyin. 1 seviyeyi tavsiye ederim, bu cevabı 6 kullanır, ancak herhangi bir sabit sayı belirtilen hedefe ulaşır :-)
Steve Jessop

6
@CandiedOrange Bu cevapta "form 6" kullanmamaya şaşırdım ... kesinlikle daha az çirkin!
svidgen

6
Kazanmak için Form 6. Bir girinti seviyesi için bir tabspace. Basit ve etkili. Sorun çözüldü :)
Monica ile Hafiflik Yarışları

2
Tamam tamam, form 6, öyle. Bu JeffGrigg'in c2'de bahsettiği değişken.
candied_orange 22:16

4
@ random832 Şimdi sıkıca bisiklet kulübesi bölgesinde olduğumuzu düşünüyorum. Bunu çözmenin doğru yolu: Örnekler için kod tabanınızı arayın, mağaza stil rehberinize bakın, mağazanızdaki geliştiricilere sorun ve bunların hiçbiri yetkili bir cevap vermezse, bunu kullanın. Her iki şekilde de çözebilecek anlaşmazlıkları çözün. Çeyrek konuştuktan sonra tutarlı olun!
candied_orange 22:16

52

Aslında, okunabilirlik sorunu kesinlikle diğer yöne gider. İlk olarak, akan çizginizi beyaz boşluk kullanarak kolayca çözebilirsiniz . Ancak kaldırma constyalnızca satırı kısaltmakla kalmaz, programın anlamını da tamamen değiştirir.

Herb Sutter , en önemlisi olarak constatıfta bulunur çünkü geçici olana bağlanabilir ve ömrünü uzatabilir. Olmayan bir değer referansı , ayrı bir değişkene ihtiyacınız var.constconstconstconst

void foo_const(std::string const& );
void foo_nc(std::string& );

std::string some_getter();

foo_const(some_getter());      // OK
foo_const("Hello there"); // OK

foo_nc(some_getter()); // error
foo_nc("Nope");   // error

std::string x = some_getter(); // have to do this
foo_nc(x);                     // ok
std::string msg = "Really??";  // and this
foo_nc(msg);                   // ok

Bunun kullanılabilirlik için ne anlama geldiği, tüm bu geçici değişkenleri sadece işlevinizi çağırabilmek için tanıtmanız gerekmesidir. Bu, okunabilirlik için harika değildir, çünkü bu değişkenler anlamsızdır ve yalnızca imzanız yanlış olduğu için vardır.


6
Sizin ikinci paragraf beni olmadığını anlamaya çalışıyorum baş ağrısı verir constrefering constveya diğer constneyin constgerçekten önemli olduğunuconst
Mindwin

3
@Mindwin İroninin, ikinci paragrafımın net ve net olduğu ve bence neden bahsettiğiniz hakkında hiçbir fikrim yok.
Barry

2
@Barry Kesinlikle kesin değil, ama ne anlama geldiğini anlamaya çalışmam için bana bu paragraftan birkaç okuma aldı. Bu sorunun bir kısmının "Herb Sutter'in kurumu ifade ettiği (const referansına bakıldığında) en önemli const ..." veya "Herb Sutter'ın const olarak kullanılması (const referansı) ile ayrıştırılabilir olduğunu düşünüyorum. önemli bir konsepte ... "İkincisi kelimelerin tek geçerli gruplaması olduğuna inanıyorum, ancak onu işlemesi biraz zaman alıyor. Belki belirsizliği gidermek için tırnak işareti kullanmanın bir yolu vardır?
Cort Ammon - Monica

1
Bazı hecelenmiş bileşiklerin bunu temizleyeceğini düşünüyorum.
shawnt00

2
ya da özellikle const&orada constbir isim (-phrase) yerine referans kullanmak yerine
Caleth

21

Basit cevap "hayır" dır.

Uzun cevap, constanahtar kelimenin, işlevin sunduğu sözleşmenin bir parçası olduğudur; Size argümanın değiştirilmeyeceğini söyler. Bu constgarantiyi kaldırdığınız an pencereden dışarıya doğru gider. Eğer makul dokümantasyon, düzenleri veya yönergeleri kullanarak bir şeyin constness (veya başka bir özelliğini) muhafaza edemez unutmayın - constness derleyici tarafından zorlanan değilse, birisi olacak onlar ile boğuşmak durumunda işlerinin kolaylaştırılması düşünüyorum parametre "sadece biraz". Düşünmek:

// parameter "foo" is not modified
void fna(Foo& foo);

void fnb(const Foo& foo);

İkinci versiyonun daha özlü olmasının yanı sıra, daha güçlü kontratlar da sağlar ve derleyicinin niyetlerinizi korumanıza yardımcı olmasına izin verir. İlki, fna(Foo&)işlevin kendisine ilettiğiniz parametreyi değiştirmesini engellemek için hiçbir şey yapmaz .

@CandiedOrange yanıtında olduğu gibi, kodu düzenlemek ve okunabilirliği artırmak için boşluk kullanabilirsiniz.


14

Çıkarma constkelime kaldırır okunabilirliği çünkü constiletişim kurduğu bilgi okuyucu ve derleyiciye.
Yatay kod uzunluğunu azaltmak iyidir (kimse yana doğru kaydırmayı sevmez), ancak constmetinden daha fazlası vardır . Tekrar yazabilirsin:

typedef string str;
typedef MyObject MObj;
void MyClass::myFunction(const MObj& o,const str& s1,const str& s2,const str& s3)

Bu da sözleşmeyi değiştirmiyor ancak hat uzunluğunu azaltma ihtiyacını karşılıyor. Gerçekten , yukarıdaki pasajın daha az okunabilir olduğunu düşünürdüm ve CandiedOrange'in cevabında daha önce belirtildiği gibi daha fazla boşluk kullanmayı tercih ederim.

constkodun kendisinin bir işlevidir. İşlevi MyClass::, bildirimin bölümünü kaldırmak için üye olmayan bir üye yapmazsınız.const


4
Sağladığınız pasajın daha az okunabilir olduğuna katılıyorum. Bu öğrenmek gitmek için bir okuyucu zorlar MObjve str, ve kesinlikle şüpheyle karşılandı. Örneğin Neden sadece adını vermedi: Bu isimleri zaten üzerinde kontrole sahip türleri için özellikle tuhaf MyObjectolarak MObjbaşlamak için?
Jason C

3

Okunabilirlik, parametrelerde const kullanmamak için geçerli bir neden midir?

Hayır. Atlamak constişlevselliği değiştirebilir, korumaları kaybedebilir constve daha az verimli kod oluşturabilir.

Parametre nesnelerinin manuel olarak değişmemesi sağlanabilir mi?

Manuel olarak kod oluşturmak için zaman harcamak yerine

void MyClass::myFunction(const MyObject& obj,const string& s1,const string& s2,const string& s3){
  //
}

Otomatik biçimlendirme araçlarını kullanın . İşlevsel gereksinimlerine göre işlevi yazın ve otomatik biçimlendirmenin sunumu yönetmesine izin verin. Biçimlendirmeyi el ile ayarlamak, otomatik biçimlendirmeyi kullanmak ve kaydedilen süreyi kodun diğer yönlerini iyileştirmek için kullanmak kadar etkili değildir.

void MyClass::myFunction(const MyObject& obj, const string& s1, const string& s2, 
    const string& s3) {
  // 
}

-1

Mümkün olduğunca const'u görünür tutmak daha iyidir. Kod bakımını çok geliştirir (bu yöntemin benim argümanlarımı değiştirip değiştirmeyeceğine dair hiçbir tahmin yoktur).

Bir yöntemde çok sayıda argüman görürsem, beni daha kısa, anlaşılması daha kolay (yöntemlerin uzun argüman listesini ortadan kaldıracak) proje tabanlı jaron (Matrix, Çalışan, Dikdörtgen, Hesap) oluşturmayı düşünmeye zorlar.


Kabul. İşaret etmekte tereddüt ettim. Böylece, "aşırı durum".
16'da

@cmaster Bu, bazen belirli bağlamlarda, bazı programlayıcılarla, okunabilir kalabileceğini söyledi . Örneğin, Windows API çağrılarında bel derinliğinde bir programın çok özel bir örneğinde, o ortama alışkın bir okuyucuyla, örneğin typedef Point * LPPOINTve typedef const Point * LPCPOINTsüper iğrenç olsa da, hemen hemen beklentilerle tutarlı olduğu için, yine de örtük bir anlam taşır. bağlamında. Fakat genel davada asla; aklıma gelen tuhaf bir istisna.
Jason C

1
Evet, "imzasız uzun uzun int int" sorusunu gördüğümde aklıma geldi, ama "const" veya "referans" olmaktan fayda elde etmek iyi bir aday değil. Typedef genel kısaltma isimleri problemini çözer; fakat dil yapılarının ("const" gibi) amaçlarını arkasına gizlemek iyi bir tasarım gibi görünmüyor.
16'da
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.