2008-10-02 1 views
92

Быстрый вопрос:Const ИНТ против Int сопзЬ в качестве параметра функции в C++ и C

int testfunc1 (const int a) 
{ 
    return a; 
} 

int testfunc2 (int const a) 
{ 
    return a; 
} 

Являются ли эти две функции одинаковы в каждом аспекте, или есть разница? Я интересуюсь ответом на C-язык, но если есть что-то интересное в случае C++, которое я хотел бы знать.

+0

Есть ли ключевое слово const в C сейчас? Раньше не было, но я не очень хорошо знаком с стандартом C 99. –

+6

Вам не обязательно быть. C90 достаточно. Однако это не было в оригинальном K & R C. –

+2

Это ключевое слово в C89 и ANSI. Я не знаю, было ли это ключевое слово в днях Кринхинга и Ричи. –

ответ

146

const T и T const идентичны. Однако обратите внимание на приоритет указателя:

char const* - указатель на постоянный символ (массив), а char* const - постоянный указатель на изменяемый символ (массив).

+1

C имеет const, данный: static const char foo [] = "foo"; вам лучше не изменять foo. –

+1

У K & R C не было const; C90 (и C99). Это немного ограничено по сравнению с C++, но это полезно. –

+0

Я уже удалил эту бессмыслицу из моего текста. ;-) –

3

Да, они одинаковы для всего int

и различен для int*

+5

(const int *) и (int const *) одинаковы, они просто отличаются от (int * const). –

3

Я думаю, что в этом случае они одинаковы, но вот пример, где вопросы порядка:

const int* cantChangeTheData; 
int* const cantChangeTheAddress; 
+1

Действительно, но int const * совпадает с первым, поэтому порядок int и const не имеет значения, это просто порядок * и const, который делает. –

7

Пракаш является правильным, что заявления, то же самое, хотя и немного больше объяснений по делу указателя может быть в порядке.

«const int * p» - это указатель на int, который не позволяет изменять int с помощью этого указателя. «int * const p» - это указатель на int, который нельзя изменить, чтобы указать на другой int.

См. http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.5.

12

Нет никакой разницы. Оба объявляют «a» целым числом, которое невозможно изменить.

Место, где различия появляются, - это когда вы используете указатели.

Оба эти:

const int *a 
int const *a 

объявить «а» быть указателем на целое число, которое не меняется. «a» может быть назначено, но «* a» не может.

int * const a 

объявляет «a» постоянным указателем на целое число. «* a» может быть назначено, но «a» не может.

const int * const a 

объявляет «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; 
} 
291

Хитрость заключается в том, чтобы прочитать объявление в обратном направлении (справа налево):

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 
+71

Мне нравится трюк с обратной записью. :-) –

+20

это очень сильный совет - хорошо сделано – bph

+1

как насчет "char const * u"? Означает ли это «Указатель на постоянный символ» или «указатель, который является постоянным для символа»? Кажется двусмысленным. Стандарт гласит первый, но чтобы это выяснить, вы должны учитывать правила приоритетности и ассоциативности. –

4

Это не является прямым ответом, но связанный наконечник. Чтобы все было в порядке, я всегда использую конвекцию «положить 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 
+5

Возможно, вам лучше использовать правило «const делает const независимо от того, что осталось от него». Например. «int * const foo» делает указатель «const», потому что указатель остается ему. Однако вы должны написать вторую строку «int const * bar», которая делает int const, потому что ей остается. «int const * const * qux», делает как int, так и указатель const, потому что один из них один раз остается на нем. – Mecki

5

const int идентичен int const, как это имеет место со всеми скалярными типами в C. В общем, объявлении параметре скалярной функции, как const не требуется, поскольку вызов по значению семантики C означает, что любое изменения в переменной локальны для ее закрывающей функции.

-2

Это то же самое, но в C++ есть веская причина всегда использовать const справа. Вы будете соответствовать везде, поскольку функция сопза членов должен быть объявлена ​​следующим образом:

int getInt() const; 

Он изменяет this указателя в функции от Foo * const к Foo const * const. See here.

+2

Это совершенно другой тип const. –

+0

Почему это совсем другое? Разные достаточно, чтобы заработать нисходящее. –

+0

Да, вопрос о разнице между «const int» и «int const», ваш ответ не имеет к этому никакого отношения. –

Смежные вопросы