我声明C++变量时,像这样写:
int a,b,c,d;
或者string strA,strB,strC,strD;
即首先是类型,然后是逗号分隔的变量名称列表。
然而,我像这样声明指针:
int *a,*b,*c,*d;
以及类似这样的引用:
int &a,&b,&c,&d;
为了保持一致,应该是:
int* a,b,c,d;
和
int& a,b,c,d;
为什么它不是一致的?
我声明C++变量时,像这样写:
int a,b,c,d;
或者string strA,strB,strC,strD;
即首先是类型,然后是逗号分隔的变量名称列表。
然而,我像这样声明指针:
int *a,*b,*c,*d;
以及类似这样的引用:
int &a,&b,&c,&d;
为了保持一致,应该是:
int* a,b,c,d;
和
int& a,b,c,d;
为什么它不是一致的?
*
这样的东西应用于变量而不是类型的最好答案是这样的想法:声明应该跟随使用。基本上,你如何声明一个变量应该看起来类似于你如何使用一个变量。
例如,
int *a, b;
...
*a = 42;
b = 314159;
...使用a
和b
的方式类似于声明a
和b
。
甚至C语言的创建者之一Dennis Ritchie也为此行为提供了引用:
类比推理导致了名称的声明语法与表达式语法相似,这些名称通常出现在表达式中...在所有这些情况下,变量的声明类似于其类型为声明头部所命名的表达式中的使用。
p: ^Integer;
。 - cyco130这是由于C语言的遗产。*
修改符在C中用于变量。因此,由于无法更改第一个而破坏C兼容性,C++设计者通过类比制定了将 &
应用于变量的规则。数组语法也是如此。
int anInt, *aPointerToInt, anArrayOfInt[100];
Bjarne Stroustrup在他的书《C++的设计与演化》中表示,他不满意这一点,但由于需要与C语言兼容,他不得不接受它。他特别对此感到不满意的是:
int *a[10];
从声明中无法确定a
是指向一个数组还是一个指向指针的数组(它是一个指向指针的数组,你需要使用方括号来覆盖默认的声明)。
当然,您始终可以使用typedef
来使代码变得更简洁。
&
和*
实际上适用于变量而不是类型。int *a, *b, *c, *d;
写下int* a, b;
的意思是
int *a;
int b;
int *a;
而不是int* a;
,这只是代码风格的问题。int*
是一种类型,但是C语法明确规定,在变量声明中*
和&
将应用于变量。int a[10], b;
std::cout << typeid(a).name() << std::endl; // it will print int[10]
std::cout << typeid(b).name() << std::endl; // it will print int
在其他语言(如C#)中,使用的语法是int[] array;
。
另一件事是指向函数的语法:
// Now we declare a variable that is a pointer to function
int (*pt2Function)(char, char) = NULL;
我们正在将 *
应用到变量名中。
在我看来,虽然我们中有90%的人喜欢不同的方式,但对变量应用 *
和 &
更符合语言的其他部分。
同样地,在处理数组时也是如此:
// Now we declare a variable that is a pointer to an array of 10 integers.
int (*arrayptr)[10];
typedef int* intptr; intptr a,b,c,d;
- Sodvedtypedef int* intptr; intptr a, b, c, d;
。 - tenfourC语言有一个声明规则:声明与使用相似。这意味着变量的声明看起来像变量的使用方式。例如:
int i;
int *i;
*i
,这个表达式的结果是一个int
。这也意味着一个表达式i
的结果是一个指向int
的指针。int i(void);
i()
,并且会得到一个 int
。这也意味着 i
是一个不带参数并返回一个 int
的函数。int (*i[5])();
(*i[x])()
,结果为int
。这也意味着*i[x]
是返回int
的函数,i[x]
是返回int
的函数指针,i
是一个返回int
的函数指针数组。int a, *b, c(void), (*d[5])(void);
声明了几个表达式,它们都具有int
类型,但变量本身并不全是int
。
N.B. 在函数和数组的声明中,子声明并不与变量的使用直接相似。即int i [5];
并不意味着在使用i
时需要将“5”放在方括号内,而int i(int);
也不意味着您调用函数时需要说i(int);
。此外,结构类型的变量声明与使用不匹配,因为您必须为每个成员变量声明表达式。
与声明变量的语法相关的是typedef的语法。要声明具有特定类型的typedef,您可以使用与声明所需类型的变量相同的语法,但在声明前面加上typedef
,变量名成为typedef名称。
typedef int (*array_of_function_pointers[5])(void);
C++增加了引用,模板和成员指针等诸多内容。它试图在某种程度上遵循旧的C约定,但这种约定对于C++添加的许多东西并不真正有效,因此您会开始出现不一致性。您只需要学习其特点,并将其归结为C和C++之间不完美的融合。
C++继承了C语言的语法。K&R书籍(§5.1)中提到该表达式
int *ip, **ipp;
这里的意图是希望使用mnemonic(即你读到“*ip
和**ipp
具有类型int
”时,你可以记忆它),他们想要模仿使用语法。
我认为对人类来说这相当难以理解且反直觉,并且与typedef不一致,例如:
typedef int* intptr;
intptr a, b; // equivalent to: int *a, *b
但实际上,这并不是C++作者的决定。让这种语言与C兼容意味着使用这种语法。
typedef
更不一致。 - Flexotype+qualif
functionid
args
。 - v.oddou
*
或者&
,而不是放在变量前面。总之,这种用法源自 C++ 的 C 根基。 - Some programmer dudeconst
应用于类型,而不是变量。就像在函数签名中,星号应用于返回类型,而不是函数的标识符。 - v.oddou