Их два cv-qualifiers, const и volatile. Каждый cv-qualifierдолжен появляться не более одного раза в cv-qualifier-seq. Если a cv-qualifierпоявляется в a decl-specifier-seq, то init-declarator-list или member-declarator-listдекларации не может быть пустым. [ Note: [basic.type.qualifier] и [dcl.fct] опишите, как cv-квалификаторы влияют на типы объектов и функций. ] Избыточные CV-квалификации игнорируются. [ Например, они могут быть введены с помощью typedefs. ] — end note Note: — end note
[ Note: Объявление переменной const может повлиять на ее linkage ([dcl.stc]) и удобство использования в constant expressions. Как описано в [dcl.init], определение объекта или подобъекта типа с указанием const должно указывать инициализатор или подвергаться инициализации по умолчанию. ] — end note
Указатель или ссылка на cv-квалифицированный тип не обязательно должны указывать или ссылаться на cv-квалифицированный объект, но он обрабатывается так, как если бы он это делал; Путь доступа с указанием констант не может использоваться для изменения объекта, даже если указанный объект не является константным объектом и может быть изменен с помощью другого пути доступа. [ Note: Cv-квалификаторы поддерживаются системой типов, так что без них их нельзя ниспровергнуть casting. ] — end note
За исключением того, что любой объявленный член класса mutable может быть изменен, любая попытка изменить const объект во время его выполнения lifetime приводит к неопределенному поведению. [ Example:
const int ci = 3; // cv-qualified (initialized as required) ci = 4; // ill-formed: attempt to modify const int i = 2; // not cv-qualified const int* cip; // pointer to const int cip = &i; // OK: cv-qualified access path to unqualified *cip = 4; // ill-formed: attempt to modify through ptr to const int* ip; ip = const_cast<int*>(cip); // cast needed to convert const int* to int* *ip = 4; // defined: *ip points to i, a non-const object const int* ciq = new const int (3); // initialized as required int* iq = const_cast<int*>(ciq); // cast required *iq = 4; // undefined: modifies a const object
Другой пример:
struct X { mutable int i; int j; }; struct Y { X x; Y(); }; const Y y; y.x.i++; // well-formed: mutable member can be modified y.x.j++; // ill-formed: const-qualified member modified Y* p = const_cast<Y*>(&y); // cast away const-ness of y p->x.i = 99; // well-formed: mutable member can be modified p->x.j = 99; // undefined: modifies a const member
— end example ]
Семантика доступа через изменчивое значение glvalue определяется реализацией. Если предпринята попытка доступа к объекту, определенному с типом с изменяемым атрибутом, с помощью энергонезависимого значения glvalue, поведение не определено.
[ Note: volatile является подсказкой реализации, чтобы избежать агрессивной оптимизации, связанной с объектом, потому что значение объекта может быть изменено средствами, не обнаруживаемыми реализацией. Кроме того, для некоторых реализаций volatile может указывать на то, что для доступа к объекту требуются специальные аппаратные инструкции. См. [intro.execution] Подробную семантику. В общем, семантика volatile в C ++ должна быть такой же, как и в C. ] — end note