Kod gözden geçirme işleminde, iş arkadaşlarımdan biri, üstbilgide bir işlev parametresi olarak kullanılan "ilkel türler" in önündeki "const" öğelerinin anlamsız olduğunu ve bu "const" leri kaldırmayı önerdiğini söyledi. Bu tür durumlarda yalnızca kaynak dosyada "const" kullanılmasını önerdi. İlkel tipler "int", "char", "float" vb.
Aşağıdaki örnek.
example.h
int ProcessScore(const int score);
example.cc
int ProcessScore(const int score) {
// Do some calculation using score
return some_value;
}
Onun önerisi şöyle yapıyor:
example.h
int ProcessScore(int score); // const is removed here.
example.cc
int ProcessScore(const int score) {
// Do some calculation using score
return some_value;
}
Ama biraz kafam karıştı. Genellikle, kullanıcı yalnızca başlığa bakar, bu nedenle başlık ve kaynak dosya arasında tutarsızlık varsa, karışıklığa neden olabilir.
Bu konuda biraz tavsiyede bulunabilir mi?
İçin herşey türleri (sadece ilkel değil) Üst düzey işlev bildirgesindeki const niteleyicileri yoksayılır. Yani aşağıdaki dört, aynı işlevi bildirir:
void foo(int const i, int const j);
void foo(int i, int const j);
void foo(int const i, int j);
void foo(int i, int j);
Const niteleyici işlev içinde yok sayılmaz. vücut, ancak. Orada const doğruluğu üzerinde etkisi olabilir. Ama bu fonksiyonun bir uygulama detayıdır. Yani genel fikir birliği:
-
Konsolu bildirimden çıkar. Bu sadece dağınıklık ve istemcilerin işlevi nasıl arayacağını etkilemez.
-
Const bırakın tanımında Derleyicinin parametrenin yanlışlıkla değiştirilmesini yakalamak için isterseniz.
Aşırı yük çözünürlüğüne geldiğinde const olarak adlandırılan ve const olmadan işlev parametresi aynıdır. Yani örneğin işlevler
void f(int);
void f(const int);
aynıdır ve birlikte tanımlanamaz. Sonuç olarak, olası kopyalardan kaçınmak için tüm parametreler için bildirimde const kullanmamak daha iyidir. (Const constifier veya const pointer hakkında konuşmuyorum - const düzenleyici üst düzey değil.)
İşte standarttan kesin alıntı.
Listeyi oluşturduktan sonra
Parametre türlerinin, bir parametre türünü değiştiren herhangi bir üst düzey cv-niteleyicileri, oluştururken silinir
işlev türü. Elde edilen transforme edilmiş parametre türleri ve elipsin varlığı veya yokluğu
veya bir işlev parametre paketi, işlevin parametre türü listesidir. [Not: Bu dönüşüm değil
parametrelerin türlerini etkiler. Örneğin,
int(*)(const int p, decltype(p)*) ve
int(*)(int, const int*) aynı türlerdir. - not notu]
Fonksiyon tanımındaki kurgunun faydası tartışmalıdır - bunun ardındaki akıl yürütme aynıdır yerel değişkeni bildirmek için const kullanma - Diğer programcılara kodun okunması, bu değerin işlev içinde değiştirilmeyeceğini gösterir.
Kod incelemesinde verilen tavsiyelere uyun.
kullanma
const Değer argümanlarının semantik değeri yoktur - fonksiyonunuzun uygulanması için sadece anlamlı (potansiyel olarak) - ve bu durumda bile gereksiz olduğunu iddia ederim.
Düzenle:
Sadece açık olmak gerekirse: işlevinizin prototipi genel arayüz senin fonksiyonuna Ne
const referansları değiştirmeyeceğinizi garanti eder.
int a = 7;
do_something( a );
void do_something( int& x ); // 'a' may be modified
void do_something( const int& x ); // I will not modify 'a'
void do_something( int x ); // no one cares what happens to x
kullanma
const TMI'ya benzer bir şeydir - 'x' değiştirilmiş olsun ya da olmasın, işlevin dışında hiçbir yerde önemli değildir.
edit2: Ayrıca bilgileri de çok beğeniyorum StoryTeller’ın cevabı
Diğer birçok kişi, API perspektifinden yanıtladığı gibi, hepsi de eşdeğerdir ve aşırı yüklenme için eşittir:
void foo( int );
void foo( const int );
Ama daha iyi bir soru, bunun sağlanıp sağlanmadığıdır. herhangi bir anlamsal anlam bu API’nın bir tüketicisine ya da herhangi bir geliştirici Uygulamanın
Bunu açıkça tanımlayan iyi tanımlanmış bir geliştirici kodlama yönergeleri olmadan,
const Skaler argümanların açıkça belirgin semantik anlamı yoktur.
Bir tüketiciden:
const int girişinizi değiştirmez. Hala bir literal olabilir veya başka bir değişkenden olabilir (her ikisi de
const veya olmayan
const)
Bir geliştiriciden:
const int bir kısıtlama getiriyor yerel kopya değişkenin (bu durumda, bir işlev argümanı). Bu sadece argümanı değiştirmek anlamına gelir, değişkenin başka bir kopyasını alır ve bunun yerine değiştirirsiniz.
Bir argüman by-value değerini kabul eden bir işlevi çağırırken, çağrılan işlev için yığında bu argümanın bir kopyası yapılır. Bu işlev, tüm kapsamı için, daha sonra değiştirilebilen, hesaplamalar için kullanılan vb. - çağrıya iletilen orijinal girişi etkilemeden argümanın yerel bir kopyasını verir. Etkin olarak, bu, girdisinin yerel değişken argümanını sağlar.
Argümanı
constBu sadece bu kopyanın değiştirilemeyeceği anlamına gelir; ama öyle değil Geliştiricinin kopyalamasını ve bu kopyada değişiklik yapmasını yasaklar. Bu, başlangıçtan beri bir kopya olduğu için, uygulamanın içinden çok fazla zorlamıyor - ve sonuçta tüketicinin bakış açısından çok fark yaratmıyor.
Bu tam tersi referans ile geçmek, burada bir referans
int& semantik olarak farklıdır
const int&. İlk, girişini mutasyona sokabilir; ikincisi sadece girdiyi gözlemleyebilmektedir (
const_cast
const-uzaklık - ama bu olasılığı görmezden gelelim); Böylece,
constReferanslardaki anlam, anlamsal anlam taşır.
Kamu API'sında çok fayda sağlamaz; ve (imo) uygulamada gereksiz kısıtlamalar getirmektedir. Rasgele, mahrem bir örnek olarak - basit bir işlev gibi:
void do_n_times( int n )
{
while( n-- > 0 ) {
// do something n times
}
}
şimdi gereksiz bir kopya kullanılarak yazılmalıdır:
void do_n_times( const int n )
{
auto n_copy = n;
while( n_copy-- > 0 ) {
// do something n times
}
}
Ne olursa olsun
const Kamu API'sında skaler kullanılır, bir anahtar şey olmaktır tutarlı tasarım ile. API kullanımı arasında rastgele değişirse
const skaler argümanlar kullanmak
const Skaler, daha sonra tüketiciye ima edilen anlamın var olup olmadığı konusunda kafa karışıklığına neden olabilir.
TL; DR:
const Genel bir API'daki skaler türler, alan adınız için kendi yönergeleriniz tarafından açıkça tanımlanmadıkça anlamsal bir anlam taşımamaktadır.
ben düşünce o
const derleyici için bazı ifadelerin değişmediği ve buna göre optimize etmenin bir ipucudur. Mesela sayının kareköküne kadar bölenleri arayarak bir sayının asal olup olmadığını test ediyordum ve argümanı açıkladığını düşündüm.
const alırdı
sqrt(n) dışında
for Döngü, ama yapmadı.
Başlıkta gerekli olmayabilir, ama sonra tekrar ihtiyacın tek şey argümanı değiştirmemek ve asla gerekli olmadığını söyleyebilirsin. Görmeyi tercih ederim
const sadece kaynakta değil, aynı zamanda başlıkta da bulunur. Beyanname ve tanım arasındaki tutarsızlıklar beni ihtiyatlı kılar. Sadece benim düşüncem.