C ++ Const Kullanımı Açıklaması


99
const int* const Method3(const int* const&) const;

Birisi sabitlerin her birinin kullanımını açıklayabilir mi?


27
Karmaşık bildirimleri deşifre etmek için bu yöntemi gerçekten seviyorum: c-faq.com/decl/spiral.anderson.html
Jason

Yanıtlar:


77

Bunu okuyun: https://isocpp.org/wiki/faq/const-correctness

Son const, işlevin Method3sınıfının değişken olmayan üyelerini değiştirmediği anlamına gelir .

const int* constsabit bir int için sabit bir işaretçi anlamına gelir: yani değiştirilemeyen bir işaretçi, değiştirilemeyen bir int için: bununla arasındaki tek fark const int&şu olabilirnull

const int* const&sabit bir int için sabit bir göstericiye bir başvuru anlamına gelir. Genellikle işaretçiler referans olarak aktarılmaz; const int* &daha mantıklıdır çünkü bu, göstericinin yöntem çağrısı sırasında değiştirilebileceği anlamına gelir; bu, bir göstericiyi referans olarak geçirmeyi görebilmemin tek nedeni , muhtemelen daha az verimli olması dışında const int* const&tüm amaç ve amaçlarla aynıdır. const int* constişaretçiler düz eski veri (POD) türleridir ve bunlar genellikle değere göre aktarılmalıdır.


104

Bunu tamamen eşdeğer olarak yazarsanız anlamak daha kolay

// v───v───v───v───v───v───v───v───v───v───v───v─┬┐
//                                               ││
//  v──#1    v─#2             v──#3    v─#4      #5
   int const * const Method3(int const * const&) const;

sonra sağdan sola doğru okuyun.

# 5, soldaki tüm işlev bildiriminin olduğunu söylüyor const, bu da bunun özgür bir işlevden ziyade zorunlu bir üye işlev olduğunu ima ediyor.

# 4, soldaki işaretçinin const(farklı bir adresi gösterecek şekilde değiştirilemeyebilir) olduğunu söylüyor .

# 3 int, soldan const(farklı bir değere sahip olacak şekilde değiştirilemez) diyor .

# 2, soldaki işaretçinin olduğunu söylüyor const.

# 1 int, soldan olduğunu söylüyor const.

Hepsini bir araya koyarsak, bunu bir göstericiye (veya tercih ederseniz a) bir göstericiye başvuran ve ( ) ' ye bir işaretçi döndüren constadlı bir üye işlev olarak okuyabilirsiniz .Method3constint constconst intconstint constconst int

(Not # 2 tamamen gereksizdir .)


22

Öncelikle const Teşdeğerdir T const.

const int* constbu nedenle eşdeğerdir int const * const.

constİçinde çok sayıda simge ve işaret bulunan ifadeleri okurken , bunları her zaman sağdan sola doğru okumaya çalışın (yukarıdaki dönüşümü uyguladıktan sonra). Bu durumda, dönüş değeri bir constint için bir const göstericisidir . constDönüş değeri değiştirilebilecek bir değer olmadığı için göstericinin kendisini yapmak burada bir anlam ifade etmiyor. Pointee yapmak const, ancak, arayanın tarafından döndürülen int(veya dizileri int) değiştiremeyeceğini garanti eder Method3.

const int*const&olur int const*const&, bu nedenle bu, bir const'a yönelik bir const işaretçisine başvurudurint . Bir const işaretçisini erkek constreferanslarıyla geçirmek de anlamsızdır - işaretçi olduğundan ve referanslar ve işaretçiler eşit depolama alanı kapladığından , başvurulan değeri değiştiremezsiniz, böylece yer tasarrufu da olmaz.

Sonuncusu const, yöntemin thisnesneyi değiştirmediğini gösterir. thisYöntem gövdesinin içindeki işaretçi (teorik) beyanı olacaktır T const * const this. Bu, bir const T*nesnenin arayabileceği anlamına gelir T::Method3().


2
Bunu (ve ildjarn'ın benzer cevabını) oylamak, kısmen ilk s'leri cümlenin başına koymazsanız her şeyin daha anlamlı olduğunu vurgulamak için const. İşte tam da bu yüzden const, dil izin verse de oraya koymanın kötü bir uygulama olduğunu düşünüyorum ve en yaygın kullanım budur.
TED

12

Kurallarını hatırlamanın kolay bir yolu, constonu şu şekilde düşünmektir: constsolunda hiçbir şey yoksa, solundaki şey için geçerlidir.

Bu durumda const int * const, birinci sabitin solunda hiçbir şey yoktur, bu nedenle geçerli olur intve ikincinin solunda bir şey vardır, bu nedenle işaretçiye uygulanır.

Bu kural, sahip olduğunuz durumda ne olacağını da söyler const int const *. Her iki sabit de intbu ifade için geçerli olduğundan gereksiz ve dolayısıyla geçersizdir.


3
const /* don't modify the int or array of ints' value(s) */
int* const /* as a retval, ignored. useless declaration */
Method3(const /* don't modify the int or array of ints' value(s) */
int* const /* don't modify the pointer's value, the address to which `pointer` points to. e.g. you cannot say `++pointer` */
&) const; /* this method does not modify the instance/object which implements the method */

3

Tanımlayıcı adından başlayarak (bu durumda ) şifresini çözmek için soldan sağa, geri sola vb. Okuduğunuz "saat" veya "spiral" yöntemini kullanmayı seviyorum. Method3adlandırma kuralları. Yani const int* const Method3(const int* const&) const, herhangi bir sınıf üyesini (adlandırılmamış bir sınıfın) değiştirmeyen ve bir sabiti işaret eden intve bir sabite sabit bir işaretçi döndüren bir işaretçiye sabit bir referans alan bir sınıf yöntemi int.

Bu yardımcı olur umarım,

Jason


2

C ++ 'daki const'ı hatırlamanın kolay bir yolu, aşağıdaki gibi bir kod gördüğünüz zamandır:

XXX const;
const YYY;

XXX, YYY sabit bir bileşen olacaktır
XXX const:

function ( def var ) const;    ------#1
* const;                       ------#2

const YYY form:

const int;                     ------#3
const double;

İnsanlar genellikle bu türleri kullanır. Bir yeri gördüğünüzde "const&", kafanız karışmasın, const kendisinden önce bir şeyi açıklıyor. bu yüzden bu sorunun cevabı şimdi apaçık ortada.

const int* const Method3(const int* const&) const;
  |          |             |          |       |
  #3         #2            #3         #2      #1

2

Ben sadece const int* const&bunun gerçekten daimi bir referans olduğunu belirtmek istiyorum const int*. Örneğin:

int i = 0;
int j = 1;
int* p = &i;
int* q = &j;
const int* const& cpref = p;
cpref = q; //Error: assignment of read-only reference 'cpref'

Bu aynı zamanda şu int* const&anlama gelir: "Sürekli bir referans int*".
Ama const int*&sürekli olmayan bir referanstır const int*.
Bu yardımcı olur umarım.


1

Sağdan sola okumak, değiştiricilerin anlaşılmasını kolaylaştırır.

Const bir int adında Method3bir const işaretçisine bir const işaretçisini döndüren bir const yöntemi.

  1. Bir const yöntemi üyeleri değiştiremez (açıkça belirtilmedikçe mutable)
  2. Bir const işaretçisi başka bir şeye işaret edecek şekilde değiştirilemez
  3. Bir const int (veya başka bir tür) değiştirilemez

1

const # 1: Method3 tarafından döndürülen işaretçi bir const int'e başvuruyor.

const # 2: İşlevin kendisi tarafından döndürülen işaretçi değeri sabittir. Bu işe yaramaz bir sabittir (dilbilgisi açısından geçerli olsa da), çünkü bir işlevin dönüş değeri bir l-değeri olamaz.

const # 3: İşleve başvurularak iletilen işaretçi türü bir const int'i işaret eder.

const # 4: İşleve referansla iletilen işaretçi değeri, kendisi bir const göstericisidir. Const olarak bir işleve aktarılan bir değeri bildirmek normalde anlamsız olacaktır, ancak bu değer referansla iletilir, bu nedenle anlamlı olabilir.

const # 5: İşlev (muhtemelen bir üye işlev) const'dir, yani (a) parçası olduğu nesnenin herhangi bir üyesine yeni değerler atamasına veya (b) const olmayan bir üye işlevini çağırmasına izin verilmez. nesnede veya üyelerinden herhangi birinde.


0
  • const yöntemin sonunda, nesnenin durumunun değişmeyeceğini belirten niteleyici bulunur.

  • const int*const&bir const konumuna bir const işaretçisine başvurarak almayı belirtir. Farklı bir konuma işaret etmek için değişemez veya işaret ettiği değeri değiştiremez.

  • const int*const aynı zamanda sabit bir konuma sabit bir işaretçi olan dönüş değeridir.


0

Bu kavramı göstermek için birkaç örnek güzel olabilir, daha iyi imho.

class TestClass
{
private:
   int iValue;
   int* oValuePtr;
   int& oValueRef;

public:
   int TestClass::ByValMethod1(int Value)
   {
      // Value can be modified
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   int TestClass::ByValMethod2(const int Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   const int TestClass::ByValMethod3(int Value)
   {
      // Value can be modified
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   const int TestClass::ByValMethod4(const int Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   const int TestClass::ByValMethod5(const int Value) const
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // iValue *cannot* be modified
      // Access through a const object
      iValue = Value;
      iValue += 1;

      // Return value *cannot* be modified
      // Access through a const object
      return ++iValue;
   }

   int& TestClass::ByRefMethod1(int& Value)
   {
      // Value can be modified
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   int& TestClass::ByRefMethod2(const int& Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   const int& TestClass::ByRefMethod3(int& Value)
   {
      // Value can be modified
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   const int& TestClass::ByRefMethod4(const int& Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   const int& TestClass::ByRefMethod5(const int& Value) const
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   int* TestClass::PointerMethod1(int* Value)
   {
      // Value can be modified
      Value++;

      // oValuePtr can be assigned
      oValuePtr = Value;

      // oValuePtr can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   int* TestClass::PointerMethod2(const int* Value)
   {
      // Value can be modified
      Value++;

      // oValuePtr cannot be assigned
      // const int* to int*
      oValuePtr = Value;

      // oValuePtr can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   const int* TestClass::PointerMethod3(int* Value)
   {
      // Value can be modified
      Value++;

      // oValuePtr can be assigned
      oValuePtr = Value;

      // iValue can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   const int* TestClass::PointerMethod4(const int* Value)
   {
      // Value cannot be modified
      Value++;

      // oValuePtr *cannot* be assigned
      // const int* to int*
      oValuePtr = Value;

      // oValuePtr can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   const int* TestClass::PointerMethod5(const int* Value) const
   {
      // Value can be modified
      ++Value;

      // oValuePtr *cannot* be assigned
      // const int* to int* const
      // Access through a const object
      oValuePtr = Value;

      // oValuePtr *cannot* be modified
      // Access through a const object
      oValuePtr += 1;

      // Return value *cannot* be modified
      return ++oValuePtr;
   }
};

Umarım bu yardımcı olur!

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.