[lex.key]
Изменение: новые ключевые
слова В C ++ добавлены новые ключевые слова; см[lex.key].
Обоснование:
эти ключевые слова были добавлены для реализации новой семантики C ++.
Влияние на исходную функцию:
изменение семантики четко определенной функции. Любые программы ISO C, которые использовали любое из этих ключевых слов в качестве идентификаторов, не являются допустимыми программами C ++.
Сложность преобразования:
синтаксическое преобразование. Преобразовать одну конкретную программу очень просто. Преобразование большого набора связанных программ требует больше работы.
Насколько широко используется:
Обычный.
[lex.ccon]
Изменение: Тип символьного литерала изменен сint наchar.
Обоснование:
это необходимо для улучшенного сопоставления типов аргументов перегруженной функции. Например:
int function( int i ); int function( char c ); function( 'x' );
Предпочтительно, чтобы этот вызов соответствовал второй версии функции, а не первой.
Влияние на исходную функцию:
изменение семантики четко определенной функции. Программы ISO C, зависящие от
sizeof('x') == sizeof(int)
не будет работать так же, как программы на C ++.
Сложность конвертации:
Простая.
Насколько широко используется:
Зависящие отsizeof('x') него программы, вероятно, встречаются редко.
Подпункт[lex.string]:
Изменение: строковые литералы сделаны константными.
Тип строкового литерала изменяется с «массивchar» на «массив изconst char». Типchar16_t строкового литерала изменяется с «массивsome-integer-type» на «массив изconst char16_t». Типchar32_t строкового литерала изменяется с «массивsome-integer-type» на «массив изconst char32_t». Тип широкого строкового литерала изменяется с «массивwchar_t» на «массив изconst wchar_t».
Обоснование:
это позволяет избежать вызова несоответствующей перегруженной функции, которая может рассчитывать на изменение своего аргумента.
Влияние на исходную функцию:
изменение семантики четко определенной функции.
Сложность преобразования:
синтаксическое преобразование. Исправление состоит в том, чтобы добавить приведение:
char* p = "abc"; // valid in C, invalid in C++ void f(char*) { char* p = (char*)"abc"; // OK: cast added f(p); f((char*)"def"); // OK: cast added }
Насколько широко используется:
программы, у которых есть законные основания рассматривать строковые литералы как указатели на потенциально изменяемую память, вероятно, встречаются редко.
[basic.def]
Изменение: C ++ не имеет «предварительных определений», как в C.
Например, в области видимости файла,
int i; int i;
допустимо в C, недопустимо в C ++. Это делает невозможным определение взаимно ссылочных локальных статических объектов файла, если инициализаторы ограничены синтаксическими формами C.Например,
struct X { int i; struct X* next; }; static struct X a; static struct X b = { 0, &a }; static struct X a = { 1, &b };
Обоснование:
это позволяет избежать использования разных правил инициализации для основных типов и типов, определяемых пользователем.
Влияние на исходный объект:
удаление семантически четко определенного объекта.
Сложность преобразования:
семантическое преобразование. В C ++ инициализатор для одного из набора взаимно-ссылочных локальных статических объектов должен вызывать вызов функции для выполнения инициализации.
Насколько широко используется:
редко.
[basic.scope]
Изменение: Astruct - это область видимости в C ++, а не C.
Обоснование:
область видимости класса имеет решающее значение для C ++, а структура - это класс.
Влияние на исходную функцию:
изменение семантики четко определенной функции.
Сложность преобразования:
семантическое преобразование.
Насколько широко используются:
программы на C используютсяstruct чрезвычайно часто, но изменение заметно только тогдаstruct, когда имена перечисления или перечислителя упоминаются внеstruct. Последнее, вероятно, встречается редко.
[basic.link] [также[dcl.type]]
Изменение: имя области видимости файла, которое явно объявленоconst, а не объявлено явноextern, имеет внутреннюю связь, тогда как в C оно будет иметь внешнюю связь.
Обоснование:
посколькуconst объекты могут использоваться в качестве значений во время трансляции в C ++, эта функция побуждает программистов предоставлять явный инициализатор для каждогоconst объекта. Эта функция позволяет пользователю помещатьconst объекты в исходные файлы, которые включены более чем в одну единицу перевода.
Влияние на исходную функцию:
изменение семантики четко определенной функции.
Сложность преобразования:
семантическое преобразование.
Насколько широко используется:
редко.
[basic.start.main]
Изменение:main функция не может вызываться рекурсивно и не может быть его адрес взят.
Обоснование:main функция может потребовать специальных действий.
Влияние на исходный объект:
удаление семантически четко определенного объекта.
Сложность конвертации:
Тривиально: создайте посредническую функцию, такую как
mymain(argc, argv).
Насколько широко используется:
редко.
[basic.types]
Изменение: C допускает «совместимые типы» в нескольких местах, а C ++ - нет.
Например, идентичныеstruct типы с разными именами тегов «совместимы» в C, но являются совершенно разными типами в C ++.
Обоснование:
для C ++ необходима более строгая проверка типов.
Влияние на исходный объект:
удаление семантически четко определенного объекта.
Сложность преобразования:
семантическое преобразование. Механизм «безопасного соединения» обнаружит множество, но не все, таких проблем. Те проблемы, которые не обнаруживаются с помощью безопасного связывания, будут продолжать функционировать должным образом в соответствии с «правилами совместимости компоновки» настоящего международного стандарта.
Насколько широко используется:
Обычный.
[conv.ptr]
Изменение: для преобразованияvoid* в тип указателя на объект требуется приведение типов.
char a[10]; void* b=a; void foo() { char* c=b; }
ISO C примет такое использование указателя на void, присвоенного указателю на тип объекта. C ++ не будет.
Обоснование:
C ++ больше старается, чем C, обеспечить безопасность типов во время компиляции.
Влияние на исходный объект:
удаление семантически четко определенного объекта.
Сложность конвертации:
Можно автоматизировать. Нарушения диагностирует переводчик C ++. Исправление заключается в добавлении литья. Например:
char* c = (char*) b;
Насколько широко используется:
это довольно широко используется, но хорошая практика программирования - добавлять приведение при назначении указателя на пустоту для указателя на объект. Некоторые переводчики ISO C выдают предупреждение, если приведение не используется.
[expr.call]
Изменение: Неявное объявление функций запрещено.
Обоснование:
типобезопасная природа C ++.
Влияние на исходный объект:
удаление семантически четко определенного объекта. Примечание: исходная функция была помечена как «устаревшая» в ISO C.
Сложность преобразования:
синтаксическое преобразование. Средства для создания явных объявлений функций довольно широко распространены на рынке.
Насколько широко используется:
Обычный.
[expr.post.incr], Изменение:
оператор декремента не может использоваться с операндом.
Обоснование: функция с удивительной семантикой.
Влияние на исходную функцию: допустимое выражение ISO C, использующее оператор декремента для lvalue (например, через C typedef in ), неправильно сформировано в этом международном стандарте.[expr.pre.incr]
bool
bool <stdbool.h>
[expr.sizeof], Изменение: Типы должны определяться в объявлениях, а не в выражениях.
В C выражение sizeof или выражение приведения может определять новый тип. Например,
[expr.cast]
p = (void*)(struct x {int i;} *)0;
определяет новый тип structx.
Обоснование:
этот запрет помогает прояснить расположение определений в исходном коде.
Влияние на исходный объект:
удаление семантически четко определенного объекта.
Сложность преобразования:
синтаксическое преобразование.
Насколько широко используется:
редко.
[expr.cond],[expr.ass], Изменение: Результат условного выражения, выражений присваивания или выражений запятой может быть именующим.
Обоснование:
C ++ - объектно-ориентированный язык, в котором относительно больше внимания уделяется lvalue. Например, функции могут возвращать lvalue.
Влияние на исходную функцию:
изменение семантики четко определенной функции. Некоторые выражения C, которые неявно полагаются на преобразования lvalue-to-rvalue, дадут разные результаты. Например,[expr.comma]
char arr[100]; sizeof(0, arr)
дает
100
в C ++ и
sizeof(char*)
C.
Сложность преобразования:
программы должны добавлять явное приведение к соответствующему rvalue.
Насколько широко используется:
редко.
[stmt.switch], Изменение: теперь невозможно пропустить объявление с явным или неявным инициализатором (за исключением всего не введенного блока).
Обоснование:
Конструкторы, используемые в инициализаторах, могут выделять ресурсы, которые необходимо отменить при выходе из блока. Разрешение перехода за пределы инициализаторов потребует сложного определения распределения во время выполнения. Более того, любое использование неинициализированного объекта может привести к катастрофе. С помощью этого простого правила времени компиляции C ++ гарантирует, что если инициализированная переменная находится в области видимости, то она обязательно была инициализирована.
Влияние на исходный объект:
удаление семантически четко определенного объекта.
Сложность преобразования:
семантическое преобразование.
Насколько широко используется:
редко.[stmt.goto]
[stmt.return]
Изменение: теперь недопустимо возвращать (явно или неявно) из функции, которая, как объявлено, возвращает значение без фактического возврата значения.
Обоснование:
вызывающий и вызываемый могут предполагать довольно сложные механизмы возврата для возврата объектов класса. Если некоторые пути потока выполняют возврат без указания какого-либо значения, реализация должна включать в себя гораздо больше сложностей. Кроме того, обещание вернуть значение заданного типа, а затем не возвращать такое значение, всегда считалось сомнительной практикой, допускаемой только потому, что в очень старом C не было различий между функциями void и функциями int.
Влияние на исходный объект:
удаление семантически четко определенного объекта.
Сложность преобразования:
семантическое преобразование. Добавьте в исходный код соответствующее возвращаемое значение, например ноль.
Насколько широко используется:
редко. В течение нескольких лет многие существующие реализации C выдавали предупреждения в этом случае.
[dcl.stc]
Изменение: В C ++ спецификаторыstatic илиextern могут применяться только к именам объектов или функций.
Использование этих спецификаторов с объявлениями типов недопустимо в C ++. В C эти спецификаторы игнорируются при использовании в объявлениях типов.
Пример:
static struct S { // valid C, invalid in C++
int i;
};
Обоснование:
спецификаторы класса хранилища не имеют никакого значения, когда они связаны с типом. В C ++ члены класса могут быть объявлены с помощьюstatic спецификатора класса хранения. Разрешение указателей класса хранения в объявлениях типов может сбить с толку пользователей.
Влияние на исходный объект:
удаление семантически четко определенного объекта.
Сложность преобразования:
синтаксическое преобразование.
Насколько широко используется:
редко.
[dcl.stc]
Изменение: в C ++register не является спецификатором класса хранения.
Обоснование:
спецификатор класса хранения не действует в C ++.
Влияние на исходный объект:
удаление семантически четко определенного объекта.
Сложность преобразования:
синтаксическое преобразование.
Насколько широко используется:
Обычный.
[dcl.typedef]
Изменение: имя typedef C ++ должно отличаться от любого имени типа класса, объявленного в той же области (кроме случаев, когда typedef является синонимом имени класса с тем же именем). В C имя typedef и имя тега структуры, объявленные в одной области, могут иметь одно и то же имя (потому что у них разные пространства имен).
Пример:
typedef struct name1 { /* ... */ } name1; // valid C and C++ struct name { /* ... */ }; typedef int name; // valid C, invalid C++
Обоснование:
Для простоты использования, C ++ не требует , чтобы имя типа с префиксом ключевых словclass,struct илиunion при использовании в объявлениях объектов или слепков типа.
Пример:
class name { /* ... */ }; name i; // i has type class name
Влияние на исходный объект:
удаление семантически четко определенного объекта.
Сложность преобразования:
семантическое преобразование. Необходимо переименовать один из двух типов.
Насколько широко используется:
редко.
[dcl.type] [см. также[basic.link]]
Изменение:const объекты должны быть инициализированы в C ++, но могут быть оставлены неинициализированными в C.
Обоснование:
объект const не может быть назначен, поэтому он должен быть инициализирован для хранения полезного значения.
Влияние на исходный объект:
удаление семантически четко определенного объекта.
Сложность преобразования:
семантическое преобразование.
Насколько широко используется:
редко.
[dcl.type]
Изменение: неявный запретint.
В C ++ a decl-specifier-seq должен содержать a type-specifier, если за ним не следует декларатор для конструктора, деструктора или функции преобразования. В следующем примере в левом столбце представлен действительный C; в правом столбце представлен эквивалентный C ++:
void f(const parm); void f(const int parm); const n = 3; const int n = 3; main() int main() /* ... */ /* ... */
Обоснование:
В C ++ неявное int создает несколько возможностей для двусмысленности между выражениями, включающими функционально-подобные приведения и объявления. Явное объявление все чаще считается правильным стилем. Связь с WG14 (C) указала на поддержку (по крайней мере) отказа от неявного int в следующей версии C.
Влияние на исходную функцию:
удаление семантически четко определенной функции.
Сложность преобразования:
синтаксическое преобразование. Можно автоматизировать.
Насколько широко используется:
Обычный.
[dcl.spec.auto]
Изменение:
ключевое словоauto нельзя использовать в качестве спецификатора класса хранения.
void f() {
auto int x; // valid C, invalid C++
}
Обоснование: разрешение использоватьauto для определения типа переменной из ее инициализатора приводит к нежелательной интерпретации
auto в качестве спецификатора класса хранения в определенных контекстах.
Влияние на исходный объект: удаление семантически четко определенного объекта.
Сложность преобразования: синтаксическое преобразование.
Насколько широко используется: редко.
[dcl.enum]
Изменение: объектам C ++ перечислимого типа могут быть присвоены значения только одного и того же перечислимого типа. В C объектам перечислимого типа могут быть присвоены значения любого целочисленного типа.
Пример:
enum color { red, blue, green };
enum color c = 1; // valid C, invalid C++
Обоснование:
типобезопасная природа C ++.
Влияние на исходный объект:
удаление семантически четко определенного объекта.
Сложность преобразования:
синтаксическое преобразование. (Ошибка типа, вызванная назначением, может быть автоматически исправлена путем применения явного приведения.)
Насколько широко используется:
Часто.
[dcl.enum]
Изменение: В C ++ тип перечислителя - это его перечисление. В C тип перечислителяint.
Пример:
enum e { A }; sizeof(A) == sizeof(int) // in C sizeof(A) == sizeof(e) // in C++ /* and sizeof(int) is not necessarily equal to sizeof(e) */
Обоснование:
В C ++ перечисление - это отдельный тип.
Влияние на исходную функцию:
изменение семантики четко определенной функции.
Сложность преобразования:
семантическое преобразование.
Насколько широко используется:
редко. Единственный раз, когда это влияет на существующий код C, - это когда берется размер перечислителя. Взятие размера перечислителя - не обычная практика кодирования C.
[dcl.fct]
Изменение: в C ++ функция, объявленная с пустым списком параметров, не принимает аргументов. В C пустой список параметров означает, что количество и тип аргументов функции неизвестны.
Пример:
int f(); // means int f(void) in C++ // int f( unknown ) in C
Обоснование:
Это сделано для того, чтобы избежать ошибочных вызовов функций (т. Е. Вызовов функций с неправильным числом или типом аргументов).
Влияние на исходную функцию:
изменение семантики четко определенной функции. Эта функция была отмечена как «устаревшая» в C.
Сложность преобразования:
синтаксическое преобразование. Объявления функций, использующие стиль неполного объявления C, должны быть завершены, чтобы стать объявлениями полных прототипов. Программа может нуждаться в дальнейшем обновлении, если разные вызовы одной и той же (не являющейся прототипом) функции имеют разное количество аргументов или если тип соответствующих аргументов различается.
Насколько широко используется:
Обычный.
[dcl.fct] [см.[expr.sizeof]]
Изменение: В C ++ типы не могут быть определены в возвращаемых типах или типах параметров. В C эти определения типов разрешены.
Пример:
void f( struct S { int a; } arg ) {} // valid C, invalid C++ enum E { A, B, C } f() {} // valid C, invalid C++
Обоснование:
при сравнении типов в разных единицах перевода C ++ полагается на эквивалентность имен, тогда как C полагается на структурную эквивалентность. Что касается типов параметров: поскольку тип, определенный в списке параметров, будет находиться в области действия функции, единственные допустимые вызовы в C ++ будут из самой функции.
Влияние на исходный объект:
удаление семантически четко определенного объекта.
Сложность преобразования:
семантическое преобразование. Определения типов необходимо переместить в область файла или в файлы заголовков.
Насколько широко используется:
редко. Такой стиль определения типа считается плохим стилем кодирования.
[dcl.fct.def]
Изменение: В C ++ синтаксис определения функции исключает функцию C «старого стиля». В C синтаксис «старого стиля» разрешен, но считается устаревшим.
Обоснование:
прототипы необходимы для обеспечения безопасности типов.
Влияние на исходный объект:
удаление семантически четко определенного объекта.
Сложность преобразования:
синтаксическое преобразование.
Насколько широко используется: часто
встречается в старых программах, но уже известно, что они устарели.
[dcl.init.string]
Изменение: В C ++ при инициализации массива символов строкой количество символов в строке (включая завершающие'\0') не должно превышать количество элементов в массиве. В C массив может быть инициализирован строкой, даже если массив недостаточно велик, чтобы содержать завершающую строку'\0'.
Пример:
char array[4] = "abcd"; // valid C, invalid C++
Обоснование:
манипулирование этими незавершенными массивами стандартными строковыми функциями может привести к серьезной катастрофе.
Влияние на исходный объект:
удаление семантически четко определенного объекта.
Сложность преобразования:
семантическое преобразование. Массивы должны быть объявлены на один элемент больше, чтобы содержать завершающую строку'\0'.
Насколько широко используется:
редко. Такой стиль инициализации массива считается плохим стилем кодирования.
[class.name] [см. также[dcl.typedef]]
Изменение: В C ++ объявление класса вводит имя класса в область, в которой он объявлен, и скрывает любой объект, функцию или другое объявление с этим именем во включающей области. В C объявление внутренней области видимости имени тега структуры никогда не скрывает имя объекта или функции во внешней области.
Пример:
int x[99];
void f() {
struct x { int a; };
sizeof(x); /* size of the array in C */
/* size of the struct in C++ */
}
Обоснование:
это одна из немногих несовместимостей между C и C ++, которая может быть отнесена к новому определению пространства имен C ++, где имя может быть объявлено как тип и как не-тип в одной области, в результате чего имя, не являющееся типом, становится скрыть имя типа и требует, чтобы ключевые словаclass,struct,union илиenum использоваться для обозначения имени типа. Это новое определение пространства имен обеспечивает важные нотационные удобства для программистов на C ++ и помогает сделать использование определяемых пользователем типов как можно более похожим на использование фундаментальных типов. Было сочтено, что преимущества нового определения пространства имен намного перевешивают несовместимость с C, описанным выше.
Влияние на исходную функцию:
изменение семантики четко определенной функции.
Сложность преобразования:
семантическое преобразование. Если скрытое имя, к которому необходимо получить доступ, находится в глобальной области видимости,:: можно использовать оператор C ++. Если скрытое имя находится в области видимости блока, необходимо переименовать тип или тег структуры.
Насколько широко используется:
редко.
[class.bit]
Изменение:
Подписаны битовые поля типа plainint .
Обоснование:
оставление выбора подписи на усмотрение реализаций может привести к несогласованным определениям специализаций шаблонов. Для согласованности также была исключена свобода реализации для независимых типов.
Влияние на исходную функцию:
выбор определяется реализацией в C, но не в C ++.
Сложность преобразования:
синтаксическое преобразование.
Насколько широко используется:
редко.
[class.nest]
Изменение: В C ++ имя вложенного класса является локальным для включающего его класса. В C имя вложенного класса принадлежит той же области, что и имя самого внешнего включающего класса.
Пример:
struct X { struct Y { /* ... */ } y; }; struct Y yy; // valid C, invalid C++
Обоснование:
классы C ++ имеют функции-члены, которые требуют, чтобы классы устанавливали области действия. Правило C оставит классы как механизм неполной области видимости, который не позволит программистам на C ++ поддерживать локальность внутри класса. Согласованный набор правил области видимости для C ++, основанный на правиле C, был бы очень сложным, и программисты на C ++ не смогли бы надежно предсказать значения нетривиальных примеров, включающих вложенные или локальные функции.
Влияние на исходную функцию:
изменение семантики четко определенной функции.
Сложность преобразования:
семантическое преобразование. Чтобы сделать имя типа структуры видимым в области охватывающей структуры, тег структуры может быть объявлен в области охватывающей структуры до того, как будет определена включающая структура. Пример:
struct Y; // struct Y and struct X are at the same scope struct X { struct Y { /* ... */ } y; };
Все определения типов структур C, заключенные в другие определения структур и доступные за пределами области действия включающей структуры, могут быть экспортированы в область действия включающей структуры. Примечание: это следствие разницы в правилах области видимости, которая задокументирована в[basic.scope].
Насколько широко используется:
редко.
[class.nested.type]
Изменение: В C ++ имя typedef не может быть повторно объявлено в определении класса после использования в этом определении.
Пример:
typedef int I;
struct S {
I i;
int I; // valid C, invalid C++
};
Обоснование:
когда классы усложняются, разрешение такого переопределения после использования типа может создать путаницу для программистов на C ++ относительно того, что наI самом деле означает.
Влияние на исходный объект:
удаление семантически четко определенного объекта.
Сложность преобразования:
семантическое преобразование. Необходимо переименовать тип или член структуры.
Насколько широко используется:
редко.
[class.copy]
Изменение: Копирование летучих объектов.
Неявно объявленный конструктор копии и неявно объявленный оператор присваивания копии не могут сделать копию изменчивого lvalue. Например, в ISO C действует следующее:
struct X { int i; }; volatile struct X x1 = {0}; struct X x2 = x1; // invalid C++ struct X x3; x3 = x1; // also invalid C++
Обоснование:
Подробно обсуждалось несколько альтернатив. Изменение параметра на
volatile
const
X&
значительно усложнит создание эффективного кода для объектов класса. Обсуждение предоставления двух альтернативных сигнатур для этих неявно определенных операций вызвало безответные опасения по поводу создания двусмысленностей и усложнения правил, определяющих формирование этих операторов в соответствии с базами и членами.
Влияние на исходный объект:
удаление семантически четко определенного объекта.
Сложность преобразования:
семантическое преобразование. Если для копии требуется изменчивая семантика, необходимо предоставить конструктор или присваивание, объявленный пользователем. Если требуется энергонезависимая семантика,const_cast
можно использовать явную
.
Насколько широко используется:
редко.
[cpp.predefined]
Изменение:__STDC__ определено ли, и если да, то каково его значение, определяется
реализацией.
Обоснование:
C ++ не идентичен ISO C. Обязательное__STDC__
определение потребует от переводчиков неверных утверждений. Каждая реализация должна выбрать поведение, которое будет наиболее полезным для ее рынка.
Влияние на исходную функцию:
изменение семантики четко определенной функции.
Сложность преобразования:
семантическое преобразование.
Насколько широко используется.
Ссылки на программы и заголовки__STDC__ встречаются довольно часто.