«Const» означает «только для чтения» или что-то еще? - PullRequest
31 голосов
/ 20 декабря 2010

Что на самом деле означает const?Кажется, только чтение доступно для меня, но я не уверен, что я прав.

Если только чтение и const отличаются, кто-то может сказать мне, почему?

То, что вызвало этот вопрос, было этот ответ , где он заявляет const "просто" означает только чтение в C. Я думал, что это all const означает, независимо от того,был C или C ++.Что он имеет в виду?

Для ответа на конкретные различия в const в C против C ++ я создал новый вопрос: Чем отличается «const» в C и C ++? согласно предложению R ..

Ответы [ 7 ]

47 голосов
/ 20 декабря 2010

Объявляя переменную как const, вы указываете компилятору, что у вас нет намерений изменять эту переменную.Но это не значит, что другие не имеют!Это просто для некоторой оптимизации и уведомления об ошибке компиляции (обратите внимание, что это в основном ошибка компиляции, в то время как const == ReadOnly будет означать ошибки времени выполнения).

const не означает только чтение, потому что вы можете написать const volatile, это будет означать , оно может измениться само в любое время, но я не собираюсь его изменять.

РЕДАКТИРОВАТЬ: вот классический пример: думаю, я пишу код, который читает текущее время из отображенного в памяти порта.Учтите, что RTC отображается в память DWORD 0x1234.

const volatile DWORD* now = (DWORD*)0x1234;

Это const, потому что это порт только для чтения, и volatile, потому что каждый раз, когда я буду читать его, он будет меняться.

Также обратите внимание, что многие архитектуры эффективно делают глобальные переменные, объявленные как const только для чтения, потому что их нужно изменять в UB.В этих случаях UB проявит себя как ошибка времени выполнения.В других случаях это был бы настоящий UB:)

Вот хорошее чтение: http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html

7 голосов
/ 20 декабря 2010

Компилятор не допустит изменения чего-либо, объявленного как const. Это как вы говорите.

В основном он используется в прототипах функций, чтобы информировать пользователя о том, что функция не будет касаться того или иного при передаче указателей. Это также работает для вас как отказоустойчивый.

2 голосов
/ 20 декабря 2010

Многие люди говорят вам, что const означает, что вы не можете изменить его. Это явно ложно . const можно тривиально отбросить. Обратите внимание на этот фрагмент:

void foo(const int *somevalue)
{
   int *p = (int*) somevalue;
   *p = 256;  // OMG I AM EVIL!!!!11
}

Ваш компилятор не остановит вас от этого. Итак, какова же цель const? Я бы назвал это скорее предложением. Это напоминает вам, когда вы смотрите на прототипы функций контракта, которые ожидают ваши функции. Ваш компилятор будет кричать на вас, если вы небрежно сломаете его. (Но не если вы намеренно сломаете его, как в случае с приведенным выше составом.)

В некоторых случаях стандарт преднамеренно нарушает const. Обратите внимание на возвращаемые значения strstr, например: по определению он вернет некоторое смещение в предоставленный вами буфер const ... Но возвращаемое значение не const. Зачем? Что ж, это могло бы привести к значительному разрыву при использовании возвращаемого значения strstr в буфере, отличном от const.

1 голос
/ 21 января 2011

Два байта для идентичных байтов (за исключением комментариев) примеров минимального регистра ...

Сначала в C, gcc выдаст предупреждение ...

/* Function taking a pointer to an array of
 two read only integers.*/
void a( const int (* parray)[2]);

void b(void)
{
   int array[2] = {1,2};
   const int crray[2] = {1,2}; 
/* C reserves the right to stash this in a read-only location.*/

   a( &array); 
/* warning: passing argument 1 of ‘a’ from incompatible pointer type*/
   a( &crray); /* OK!*/
}

Теперь то же самоевещь в C ++ ... g ++ вполне доволен этим.

// Function taking a pointer to an array 
// of two integers which it promises not to modify. 
// (Unless we cast away it's constness ;-P)
void a( const int (* parray)[2]);

void b(void)
{
   int array[2] = {1,2};
   const int crray[2] = {1,2};

   a( &array); // C++ has no problem with this.
   a( &crray); // OK!
}
0 голосов
/ 19 мая 2018
const char * hello_1{ "Hello!" };
const char   hello_2[]{ "Hello!" };
char       * ptr{};

// take away the const-nes
// ptr = (char *)hello_1;
// *ptr = '*'; <-- write access violation
// hello_1 is in a read only memory

// take away the const-nes
ptr = (char *)hello_2;
*ptr = '*'; // <-- OK
// hello_2 is modifiable

Указатели указывают на память, а char * указывает на память в сегменте данных, который доступен только для чтения. Разница между char * и char [] заключается в том, что, хотя оба сегмента данных объявляются одинаково в сегменте данных, char [] считается читаемым, поскольку он помещается в стек при его использовании.

0 голосов
/ 20 декабря 2010

Const означает, что указатель или ссылка не могут использоваться для операции записи или чтения-изменения-записи без исключения const. Это НЕ означает, что стандарт C ++ пытается утверждать, что это означает (стандарт C ++ просто ошибается в этом).

Переменная определена так:

 /* auto */ int const x = 1;

явно НЕ доступен только для чтения, так как в противном случае его нельзя было бы инициализировать. Скорее, тип переменной x - это «ссылка const на int» (и НЕ ссылка на const int) или, в качестве альтернативы, lvalue const of int. Обратите внимание, что «const» связан с указателем или ссылкой, он не имеет ничего общего с хранилищем, а также с типом значения, находящегося в этом хранилище.

Это довольно прискорбно, поскольку контракт, предоставленный const, чрезвычайно слаб и, в частности, не позволяет кэшировать указанную или указанную ячейку памяти именно потому, что это НЕ означает неизменяемое хранилище.

Суть: const - это модификатор доступа , связанный с символьной ссылкой или указателем, который используется программистом, чтобы позволить провайдеру символа установить обязательство на клиенте символа или для символа клиент обещает провайдеру символов, что он не изменяет память через этот символ (например, функция, принимающая указатель const на int, обещает не изменять указатель на int).

Это не имеет ничего общего с переменными:

int const *p = (int*)malloc(sizeof(int));

и явно не имеет отношения к хранилищу (хранилище malloc всегда доступно для записи).

Вместо этого вы должны думать о const как о способе передачи инвариантов, обязательств или требований между частями программы, устанавливаемых программистом для целей программистов и распространяемых системой типов. К сожалению, система типов не является надежной и не может правильно распространять константу:

X *last;
struct X { int a; X() : a(0) { last=this; } };
X const x; // x is const?
last->a = 1; //really ??

ИМХО единственная возможность, которую компилятор может сделать хранилищем неизменным, - это фактические константы, такие как строковые литералы (возможно) или статическое (глобальное) хранение. На практике автоматическое, кучное и временное хранилище невозможно сделать доступным только для чтения.

0 голосов
/ 20 декабря 2010

C ++ позволяет определять константные функции-члены. Функции-члены const являются единственными функциями, которые вызываются для объектов const. Кроме того, функции-члены const не могут изменять какие-либо члены данных класса (если только член данных не помечен как изменяемый).

class Foo
{
    int data;

    void Bar();
    void ConstBar() const;
};

void Foo::ConstBar() const
{
    // Error! cannot modify i as ConstBar is a const member function.
    // i = 0;
}

// Usage:
const Foo foo_instance;

// Error! cannot call non-const member on a const object.
// foo_instance.Bar();

// OK
foo_instance.ConstBar();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...