在C ++和C中将'const int'与'int const'作为函数参数


115

考虑:

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

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

这两个功能在各个方面都是相同的还是有所不同?

我对C语言的答案很感兴趣,但是如果C ++语言中有一些有趣的东西,我也想知道。


现在C中有一个const关键字吗?以前不是,但是我对C 99标准不太熟悉。
Onorio Catenacci

8
您不必如此。C90就足够了。它不是原始的K&R C中的。
Mark Ba​​ker

3
它是C89和ANSI中的关键字。我不知道它在Kerningham和Richie时代是否曾经是一个关键字。
Nils Pipenbrinck,

7
本网站将“ C乱语”翻译为英语cdecl.org
Motti

5
我会说“ C乱码为英语乱码”,但仍然很好:)
Kos 2010年

Answers:


175

const T并且T const是相同的。使用指针类型会变得更加复杂:

  1. const char* 是指向常量的指针 char
  2. char const* 是指向常量的指针 char
  3. char* const 是指向(可变)的常量指针 char

换句话说,(1)和(2)是相同的。制作指针(而不是指针)的唯一方法const是使用后缀- const

这就是为什么许多人总是喜欢放在const类型的右侧(“ East const”样式):它使类型相对于类型的位置一致且易于记住(从轶事上看,它也使得对初学者的教学更容易)。


2
C确实具有const,给出:static const char foo [] =“ foo”; 你最好不要改变foo。
James Antill

4
K&R C没有const;C90(和C99)可以。与C ++相比,它有些局限,但很有用。
Mark Ba​​ker

引用也是如此吗?
2016年

1
@Ken是的,是一样的。
康拉德·鲁道夫

1
@étale-cohomology补充一点。应该一直在那里。
康拉德·鲁道夫

339

诀窍是向后(从右到左)读取声明:

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

5
那“ char const * u”呢?这是读取“指向常量字符的指针”还是“指向常量字符的指针”?似乎模棱两可。该标准说的是前者,但是要找出答案,您必须考虑优先级和关联性规则。
Panayiotis Karabassis'7年

5
@PanayiotisKarabassis所有人都应被视为形容词链,而不交换任何位置。char const *,从左至右读取为:“ pointer,const,char”。它是指向const char的指针。当您说“常量的指针”时,指针上的“常量”形容词就会出现。因此,在这种情况下,您的形容词列表应该确实是:“ const,pointer,char”。但是你是对的,这个技巧是模棱两可的。这确实是一个“技巧”,而不是确定的“规则”。
Ates Goral

5
当您声明数组,函数,指针和函数指针的百搭组合时,向后读取不再有效(可悲)。但是,您可以螺旋式读取这些混乱的声明。其他人对它们感到沮丧,于是发明了Go。
马丁JH

@Martin JH:不能通过typedef将它们分解吗?和/或使用引用消除间接关系?
彼得·莫滕森

14

没有区别。它们都将“ a”声明为不可更改的整数。

当使用指针时,开始出现差异的地方。

这两个:

const int *a
int const *a

声明“ 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;
}

最后一个例子是最简单的解释,太好了!
exru

7

Prakash的声明相同是正确的,尽管可能需要对指针的情况进行更多说明。

“ const int * p”是一个指向不允许通过该指针更改int的int指针。“ int * const p”是一个指向int的指针,该指针不能更改为指向另一个int。

参见https://isocpp.org/wiki/faq/const-correctness#const-ptr-vs-ptr-const


锚点(“ faq-18.5。”已损坏。应该引用哪个锚点(有多个带有“ const”和“ *”的
字符

@PeterMortensen:是的,链接腐烂了。谢谢。我更新了链接。
Fred Larson

5

const int与C相同int const,对于C中的所有标量类型也是如此。通常,const不需要声明标量函数参数,因为C的按值调用语义意味着对变量的任何更改都位于其封闭函数的局部。


4

这不是直接的答案,而是一个相关的提示。为了保持直线,我总是使用对流“放在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

6
您最好使用规则“ const使const剩下的东西”。例如,“ int * const foo”使指针成为“ const”,因为指针留给了它。但是,您将写第二行“ int const * bar”,使它成为int const,因为它留给了它。“ int const * const * qux”使int和指针都成为const,因为任一个都留给了它。
梅基2010年

4

它们是相同的,但是在C ++中,有充分的理由总是在右边使用const。您将在所有地方保持一致,因为const成员函数必须以这种方式声明:

int getInt() const;

它将this函数中的指针从更改Foo * constFoo const * const看这里。


3
这是一种完全不同的const。
贾斯汀·迈纳斯

1
为什么这完全不同?与众不同足以赢得反对票。
尼克·韦斯特盖特

1
是的,问题在于“ const int”和“ int const”之间的区别,您的答案与之无关。
贾斯汀·迈纳斯16/04/28

1
我说他们是一样的。但是,被接受和投票最多的答案还提供了有关指针类型的更多信息。您也否决了那些吗?
尼克·韦斯特盖特

3

是的,它们只是一样 int

和不同的 int*


5
(const int *)和(int const *)相同,只是与(int * const)不同。
James Antill

3

我认为在这种情况下它们是相同的,但是下面是一个顺序很重要的示例:

const int* cantChangeTheData;
int* const cantChangeTheAddress;

2
确实,但是int const *与第一个相同,因此int和const的顺序无关紧要,只是*和const的顺序起作用。
Mark Ba​​ker
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.