Подтвердить что ты не робот

"Const" означает только чтение или что-то еще?

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

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

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

Для ответа на конкретные различия в const в C vs С++ я создал новый вопрос: Как работает "const" отличаются в C и С++? в соответствии с предложением R..

4b9b3361

Ответ 1

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

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

EDIT: вот классический пример: рассмотрим, что я пишу код, который считывает текущее время из порта с отображением памяти. Рассмотрим, что RTC отображается в память DWORD 0x1234.

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

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

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

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

Ответ 2

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

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

Ответ 3

Многие люди говорят вам, что 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.

Ответ 4

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

Сначала в 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!*/
}

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

// Function taking a pointer to an array 
// of two integers which it promises not to modify. 
// (Unless we cast away it 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!
}

Ответ 5

С++ допускает определение функций-членов 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();

Ответ 6

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

Переменная, определенная следующим образом:

 /* auto */ int const x = 1;

явно НЕ доступен для чтения, поскольку в противном случае его нельзя было инициализировать. Скорее, тип переменной x является "reference const to int" (и NOT ссылается на const int) или альтернативно lvalue const int. Обратите внимание, что "const" ассоциируется с указателем или ссылкой, который не имеет никакого отношения к хранилищу, и типом значения, находящегося в этом хранилище.

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

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

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

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

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

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

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

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