c++ - это - константный указатель




В чем разница между const int*, const int*const и int const*? (10)

Я всегда испортил, как правильно использовать const int* , const int * const и int const * . Существует ли набор правил, определяющих, что вы можете и чего не можете сделать?

Я хочу знать все дела, и все это не касается заданий, передачи функций и т. Д.


  1. Постоянная ссылка:

    Ссылка на переменную (здесь int), которая является постоянной. Мы передаем переменную как ссылку главным образом, потому что ссылки меньше по размеру, чем фактическое значение, но есть побочный эффект, и это потому, что он похож на псевдоним на фактическую переменную. Мы можем случайно изменить основную переменную через наш полный доступ к псевдониму, поэтому мы делаем его постоянным, чтобы предотвратить этот побочный эффект.

    int var0 = 0;
    const int &ptr1 = var0;
    ptr1 = 8; // Error
    var0 = 6; // OK
    
  2. Константные указатели

    Как только постоянный указатель указывает на переменную, он не может указывать на какую-либо другую переменную.

    int var1 = 1;
    int var2 = 0;
    
    int *const ptr2 = &var1;
    ptr2 = &var2; // Error
    
  3. Указатель на константу

    Указатель, через который нельзя изменить значение переменной, которую он указывает, называется указателем на константу.

    int const * ptr3 = &var2;
    *ptr3 = 4; // Error
    
  4. Постоянный указатель на константу

    Постоянным указателем на константу является указатель, который не может ни изменить адрес, на который он указывает, ни изменить значение, сохраненное на этом адресе, и не изменять его.

    int var3 = 0;
    int var4 = 0;
    const int * const ptr4 = &var3;
    *ptr4 = 1;     // Error
     ptr4 = &var4; // Error
    

В C ++ есть много других тонких точек, окружающих константную корректность. Я предполагаю, что вопрос здесь просто о C, но я приведу некоторые связанные примеры, поскольку тег - это C ++:

  • Вы часто передаете большие аргументы, такие как строки, как TYPE const & которые не позволяют объекту либо модифицироваться, либо копироваться. Пример :

    TYPE& TYPE::operator=(const TYPE &rhs) { ... return *this; }

    Но TYPE & const имеет смысла, поскольку ссылки всегда const.

  • Вы всегда должны указывать методы класса, которые не изменяют класс как const , иначе вы не можете вызвать метод из TYPE const & ссылки. Пример :

    bool TYPE::operator==(const TYPE &rhs) const { ... }

  • Существуют общие ситуации, когда как возвращаемое значение, так и метод должны быть const. Пример :

    const TYPE TYPE::operator+(const TYPE &rhs) const { ... }

    На самом деле, методы const не должны возвращать внутренние данные класса как ссылку на не-const.

  • В результате часто приходится создавать как const, так и неконстантный метод с использованием перегрузки const. Например, если вы определяете T const& operator[] (unsigned i) const; , то вам, вероятно, также захочется неконстантная версия, заданная:

    inline T& operator[] (unsigned i) { return const_cast<char&>( static_cast<const TYPE&>(*this)[](i) ); }

Afaik, в C нет функций const, функции нечлена не могут быть const в C ++, методы const могут иметь побочные эффекты, а компилятор не может использовать функции const, чтобы избежать дублирования вызовов функций. На самом деле даже простой int const & reference может свидетельствовать о том, что значение, к которому оно относится, должно быть изменено в другом месте.


Для тех, кто не знает о правиле по часовой стрелке / спирали: начните с имени переменной, перемещайте по часовой стрелке (в данном случае, переместитесь назад) к следующему указателю или типу . Повторяйте до окончания выражения.

вот демо:


Как и многие, все отметили:

В чем разница между const X* p , X* const p и const X* const p ?

Вы должны прочитать декларации указателей справа налево.

  • const X* p означает «p указывает на X, который является const»: объект X не может быть изменен через p.

  • X* const p означает, что «p - это указатель на const, который не является const»: вы не можете изменить указатель p, но вы можете изменить объект X через p.

  • const X* const p означает, что «p - это указатель const на X, который является const»: вы не можете изменить указатель p самостоятельно, и вы не можете изменить объект X через p.


Общее правило заключается в том, что ключевое слово const применяется к тому, что предшествует ему немедленно. Исключение составляет начальная const .

  • const int* совпадает с int const* и означает «указатель на константу int» .
  • const int* const совпадает с int const* const и означает «постоянный указатель на константу int» .

Edit: Для Dos и Don'ts, если этого ответа недостаточно, не могли бы вы уточнить, что хотите?


Простое использование 'const'

Самое простое использование - объявить именованную константу. Для этого один объявляет константу, как если бы она была переменной, но добавляла 'const' перед ней. Нужно немедленно инициализировать его в конструкторе, потому что, конечно, нельзя установить значение позже, так как это изменит его. Например,

const int Constant1=96; 

создаст целочисленную константу, невообразимо названную «Константа1» со значением 96.

Такие константы полезны для параметров, которые используются в программе, но их не нужно менять после компиляции программы. Он имеет преимущество для программистов над командой «#define» препроцессора C, поскольку он понимается и используется самим компилятором, а не просто заменяется текстом программы препроцессором до достижения основного компилятора, поэтому сообщения об ошибках гораздо полезнее ,

Он также работает с указателями, но нужно быть осторожным, когда «const» определяет, является ли указатель или то, на что он указывает, постоянным или и тем, и другим. Например,

const int * Constant2 

объявляет, что Constant2 является указателем переменной на постоянное целое число и

int const * Constant2

является альтернативным синтаксисом, который делает то же самое, тогда как

int * const Constant3

объявляет, что Constant3 является постоянным указателем на переменное целое число и

int const * const Constant4

объявляет, что Constant4 является постоянным указателем на постоянное целое число. В основном «const» применяется к тому, что находится на его непосредственном левом (кроме если нет ничего там, в этом случае оно относится ко всему, что является его непосредственным правом).

ref: http://duramecho.com/ComputerInformation/WhyHowCppConst.html


Синтаксис объявления C и C ++ неоднократно описывался как неудачный эксперимент, оригинальные дизайнеры.

Вместо этого давайте назовем тип «указатель на Type »; Я назову это Ptr_ :

template< class Type >
using Ptr_ = Type*;

Теперь Ptr_<char> является указателем на char .

Ptr_<const char> является указателем на const char .

И const Ptr_<const char> является const Ptr_<const char> указателем на const char .

Там.


У меня были те же сомнения, что и вы, пока я не наткнулся на эту book от C ++ Guru Скотта Мейерса. См. Третий пункт в этой книге, где он подробно рассказывает об использовании const .

Просто следуйте этому совету

  1. Если слово const появляется слева от звездочки, то, на что указывает, является постоянным
  2. Если слово const появляется справа от звездочки, сам указатель является постоянным
  3. Если const с обеих сторон, то они постоянны

Этот вопрос точно показывает, почему мне нравится делать то, о чем я упомянул в своем вопросе, является константа после допустимого типа id?

Короче говоря, я считаю, что самый простой способ запомнить правило состоит в том, что «const» идет за тем, к чему он относится. Поэтому в вашем вопросе «int const *» означает, что int является константой, а «int * const» означает, что указатель является постоянным.

Если кто-то решает поставить его на передний план (например: «const int *»), в качестве особого исключения в этом случае он применяется к предмету после него.

Многие люди любят использовать это специальное исключение, потому что считают, что это выглядит лучше. Мне это не нравится, потому что это исключение и, таким образом, путает вещи.


Я думаю, здесь все уже сказано, но я просто хочу добавить, что вы должны остерегаться typedef ! Это не просто замена текста.

Например:

typedef char *ASTRING;
const ASTRING astring;

Тип astring - char * const , а не const char * . Это одна из причин, по которой я всегда склоняю const к праву от типа и никогда не начинаю.







const