const int против int const как параметр функции в C++ и C
Быстрый вопрос:
int testfunc1 (const int a)
{
return a;
}
int testfunc2 (int const a)
{
return a;
}
Являются ли эти две функции одинаковыми во всех аспектах или есть разница? Мне интересен ответ для языка C, но если есть что-то интересное в языке C++, я бы тоже хотел знать.
9 ответов
const T
а также T const
идентичны С типами указателей это становится более сложным:
const char*
это указатель на константуchar
char const*
это указатель на константуchar
char* const
постоянный указатель на (изменяемый)char
Другими словами, (1) и (2) идентичны. Единственный способ сделать указатель (а не указатель) const
это использовать суффикс-const
,
Вот почему многие люди предпочитают всегда ставить const
с правой стороны от типа (стиль "восточный конст"): он делает его расположение относительно типа согласованным и легко запоминающимся (он также, по-видимому, упрощает обучение новичков).
Хитрость заключается в том, чтобы прочитать декларацию в обратном направлении (справа налево):
const int a = 1; // read as "a is an integer which is constant"
int const a = 1; // read as "a is a constant integer"
Оба это одно и то же. Следовательно:
a = 2; // Can't do because a is constant
Трюк с обратным чтением особенно полезен, когда вы имеете дело с более сложными объявлениями, такими как:
const char *s; // read as "s is a pointer to a char that is constant"
char c;
char *const t = &c; // read as "t is a constant pointer to a char"
*s = 'A'; // Can't do because the char is constant
s++; // Can do because the pointer isn't constant
*t = 'A'; // Can do because the char isn't constant
t++; // Can't do because the pointer is constant
Нет никакой разницы. Они оба объявляют "a" как целое число, которое нельзя изменить.
Место, где начинают появляться различия, это когда вы используете указатели.
Обе эти:
const int *a
int const *a
объявите "a" как указатель на целое число, которое не изменяется. "a" может быть назначено, но "*a" не может.
int * const a
объявляет "а", чтобы быть постоянным указателем на целое число. "*a" может быть назначено, но "a" не может.
const int * const a
объявляет "а" постоянным указателем на постоянное целое число. Ни "a", ни "*a" не могут быть назначены.
static int one = 1;
int testfunc3 (const int *a)
{
*a = 1; /* Error */
a = &one;
return *a;
}
int testfunc4 (int * const a)
{
*a = 1;
a = &one; /* Error */
return *a;
}
int testfunc5 (const int * const a)
{
*a = 1; /* Error */
a = &one; /* Error */
return *a;
}
Пракаш прав, что декларации одинаковы, хотя немного более подробное объяснение случая указателя может быть в порядке.
"const int * p" - это указатель на int, который не позволяет изменять int через этот указатель. "int* const p" - это указатель на int, который нельзя изменить, чтобы он указывал на другое int.
См. http://www.parashift.com/c++-faq-lite/const-correctness.html.
const int
идентично int const
, как и во всех скалярных типах в C. В общем случае объявление параметра скалярной функции как const
не требуется, так как семантика вызова по значению в C означает, что любые изменения в переменной являются локальными для ее включающей функции.
Они одинаковы, но в C++ есть веская причина всегда использовать const справа. Вы будете последовательны везде, потому что функции-члены const должны быть объявлены следующим образом:
int getInt() const;
Это меняет this
указатель на функцию из Foo * const
в Foo const * const
, Посмотреть здесь.
Это не прямой ответ, а связанный совет. Чтобы держать вещи прямо, я всегда использую конвекцию const
снаружи ", где под" снаружи "я подразумеваю крайний левый или крайний правый. Таким образом, нет никакой путаницы - const относится к ближайшему предмету (типу или *
). Например,
int * const foo = ...; // Pointer cannot change, pointed to value can change
const int * bar = ...; // Pointer can change, pointed to value cannot change
int * baz = ...; // Pointer can change, pointed to value can change
const int * const qux = ...; // Pointer cannot change, pointed to value cannot change
Я думаю, что в этом случае они одинаковы, но вот пример, где порядок имеет значение:
const int* cantChangeTheData;
int* const cantChangeTheAddress;