为什么在定义指针时我们使用“type * var”而不是“type&var”?

时间:2022-09-11 19:47:50

I'm relatively new to C++ (about one year of experience, on and off). I'm curious about what led to the decision of type * name as the syntax for defining pointers. It seems to me that the syntax should be type & name as the & symbol is used everywhere else in code to refer to the variable's memory address. So, to use the traditional example of int pointers:

我对C ++比较陌生(大约一年的经验,开关)。我很好奇是什么导致了* name作为定义指针的语法的决定。在我看来,语法应该是类型和名称,因为&符号在代码中的其他地方用于引用变量的内存地址。所以,使用传统的int指针示例:

int a = 1;
int * b = &a;

would become

int a = 1;
int & b = &a

I'm sure there's some reason for this that I'm just not seeing, and I'd love to hear some input from C++ veterans.

我确定有一些原因,我只是没有看到,我很想听到C ++老手的一些意见。

Thanks, -S

6 个解决方案

#1


C++ adopts the C syntax. As revealed in "The Development of the C Language" (by Dennis Ritchie) C uses * for pointers in type declarations because it was decided that type syntax should follow use.

C ++采用C语法。正如“C语言的发展”(作者Dennis Ritchie)所揭示的那样,C使用*作为类型声明中的指针,因为决定使用类型语法。

For each object of [a compound type], there was already a way to mention the underlying object: index the array, call the function, use the indirection operator [*] on the pointer. Analogical reasoning led to a declaration syntax for names mirroring that of the expression syntax in which the names typically appear. Thus,

对于[复合类型]的每个对象,已经有一种方法可以提及底层对象:索引数组,调用函数,在指针上使用间接运算符[*]。类比推理导致了一个声明语法,用于反映名称通常出现的表达式语法的名称。从而,

int i, *pi, **ppi;

declare an integer, a pointer to an integer, a pointer to a pointer to an integer. The syntax of these declarations reflects the observation that i, *pi, and **ppi all yield an int type when used in an expression.

声明一个整数,一个指向整数的指针,一个指向整数指针的指针。这些声明的语法反映了在表达式中使用i,* pi和** ppi都会产生int类型的观察结果。

Here's a more complex example:

这是一个更复杂的例子:

int *(*foo)[4][];

This declaration means an expression *(*foo)[4][0] has type int, and from that (and that [] has higher precedence than unary *) you can decode the type: foo is a pointer to an array of size 4 of array of pointers to ints.

这个声明意味着表达式*(* foo)[4] [0]具有int类型,并且从那个(并且[]的优先级高于unary *)你可以解码类型:foo是一个指向大小数组的指针int的指针数组中的4个。

This syntax was adopted in C++ for compatibility with C. Also, don't forget that C++ has a use for & in declarations.

C ++中采用了这种语法,以便与C兼容。另外,不要忘记C ++在声明中有用。

int & b = a;

The above line means a reference variable refering to another variable of type int. The difference between a reference and pointer roughly is that references are initialized only, and you can not change where they point, and finally they are always dereferenced automatically.

上面的行表示引用另一个int类型的变量的引用变量。引用和指针之间的差别大致是引用只是初始化,并且您无法更改它们指向的位置,最后它们总是自动解除引用。

int x = 5, y = 10;
int& r = x;

int sum = r + y; // you do not need to say '*r' automatically dereferenced.

r = y; // WRONG, 'r' can only have one thing pointing at during its life, only at its infancy ;)

#2


I think that Dennis Ritchie answered this in The Development of the C Language:

我认为Dennis Ritchie在C语言的发展中回答了这个问题:

For each object of such a composed type, there was already a way to mention the underlying object: index the array, call the function, use the indirection operator on the pointer. Analogical reasoning led to a declaration syntax for names mirroring that of the expression syntax in which the names typically appear. Thus,

对于这种组合类型的每个对象,已经有一种方法可以提及底层对象:索引数组,调用函数,在指针上使用间接运算符。类比推理导致了一个声明语法,用于反映名称通常出现的表达式语法的名称。从而,

int i, *pi, **ppi;

declare an integer, a pointer to an integer, a pointer to a pointer to an integer. The syntax of these declarations reflects the observation that i, *pi, and **ppi all yield an int type when used in an expression. Similarly,

声明一个整数,一个指向整数的指针,一个指向整数指针的指针。这些声明的语法反映了在表达式中使用i,* pi和** ppi都会产生int类型的观察结果。同样的,

int f(), *f(), (*f)();

declare a function returning an integer, a function returning a pointer to an integer, a pointer to a function returning an integer;

声明一个返回整数的函数,一个返回指向整数的指针的函数,一个返回整数的函数的指针;

int *api[10], (*pai)[10];

declare an array of pointers to integers, and a pointer to an array of integers. In all these cases the declaration of a variable resembles its usage in an expression whose type is the one named at the head of the declaration.

声明一个指向整数的指针数组,以及一个指向整数数组的指针。在所有这些情况下,变量的声明类似于在表达式中的用法,该表达式的类型是在声明的头部命名的类型。

So we use type * var to declare a pointer because this allows the declaration to mirror the usage (dereferencing) of the pointer.

因此我们使用类型* var来声明指针,因为这允许声明镜像指针的使用(解除引用)。

In this article, Ritchie also recounts that in "NB", an extended version of the "B" programming language, he used int pointer[] to declare a pointer to an int, as opposed to int array[10] to declare an array of ints.

在本文中,Ritchie还在“NB”中叙述了“B”编程语​​言的扩展版本,他使用int pointer []来声明一个指向int的指针,而不是int数组[10]来声明一个数组整数。

#3


If you are a visual thinker, it may help to imagine the asterisk as a black hole leading to the data value. Hence, it is a pointer.

如果您是视觉思考者,可能有助于将星号想象为导致数据值的黑洞。因此,它是一个指针。

The ampersand is the opposite end of the hole, think of it as an unraveled asterisk or a spaceship wobbling about in an erratic course as the pilot gets over the transition coming out of the black hole.

&符号是洞的另一端,当飞行员越过从黑洞出来的过渡时,将它想象成一个散开的星号或宇宙飞船在一个不规则的过程中摇摆不定。

I remember being very confused by C++ overloading the meaning of the ampersand, to give us references. In their desperate attempt to avoid using any more characters, which was justified by the international audience using C and known issues with keyboard limitations, they added a major source of confusion.

我记得很担心C ++重载&符号的含义,给我们参考。他们绝望地试图避免使用任何更多角色,这是由国际观众使用C和键盘限制的已知问题所证明的,他们增加了一个混乱的主要来源。

One thing that may help in C++ is to think of references as pre-prepared dereferenced pointers. Rather than using &someVariable when you pass in an argument, you've already used the trailing ampersand when you defined someVariable. Then again, that might just confuse you further!

在C ++中可能有用的一件事是将引用视为预先准备好的解引用指针。传入参数时,不是使用&someVariable,而是在定义someVariable时已经使用了尾随符号。再说一遍,这可能会让你更进一步!

One of my pet hates, which I was unhappy to see promulgated in Apple's Objective-C samples, is the layout style int *someIntPointer instead of int* someIntPointer

我不喜欢看到在Apple的Objective-C示例中发布的一个宠物讨厌的是布局样式int * someIntPointer而不是int * someIntPointer

IMHO, keeping the asterisk with the variable is an old-fashioned C approach emphasizing the mechanics of how you define the variable, over its data type.

恕我直言,用变量保留星号是一种老式的C方法,强调了你如何在数据类型上定义变量的机制。

The data type of someIntPointer is literally a pointer to an integer and the declaration should reflect that. This does lead to the requirement that you declare one variable per line, to avoid subtle bugs such as:

someIntPointer的数据类型实际上是指向整数的指针,声明应该反映出来。这确实导致您要求每行声明一个变量,以避免细微的错误,例如:

int* a, b;  // b is a straight int, was that our intention?

int  *a, *b;  // old-style C declaring two pointers

int* a;
int* b;  // b is another pointer to an int

Whilst people argue that the ability to declare mixed pointers and values on the same line, intentionally, is a powerful feature, I've seen it lead to subtle bugs and confusion.

虽然有人认为有意识地在同一行上声明混合指针和值的能力是一个强大的功能,但我已经看到它会导致细微的错误和混乱。

#4


Your second example is not valid C code, only C++ code. The difference is that one is a pointer, whereas the other is a reference.

你的第二个例子不是有效的C代码,只有C ++代码。区别在于一个是指针,而另一个是参考。

On the right-hand side the '&' always means address-of. In a definition it indicates that the variable is a reference.

在右侧,'&'总是表示地址。在定义中,它表示变量是引用。

On the right-hand side the '*' always means value-at-address. In a definition it indicates that the variable is a pointer.

在右侧,'*'始终表示地址价值。在定义中,它表示变量是指针。

References and pointers are similar, but not the same. This article addresses the differences.

引用和指针类似,但不一样。本文讨论了这些差异。

#5


Instead of reading int* b as "b is a pointer to int", read it as int *b: "*b is an int". Then, you have & as an anti-*: *b is an int. The address of *b is &*b, or just b.

而不是将int * b读作“b是指向int的指针”,而是将其读作int * b:“* b是一个int”。然后,你有&作为反*:* b是一个int。 * b的地址是&* b,或者只是b。

#6


I think the answer may well be "because that's the way K&R did it."

我认为答案很可能是“因为这就是K&R的做法。”

Downvoting fools. Explain why I'm wrong.

愚弄傻瓜。解释为什么我错了。

K&R are the ones who decided what the C syntax for declaring pointers was.

K&R决定用于声明指针的C语法是什么。

It's not int & x; instead of int * x; because that's the way the language was defined by the guys who made it up -- K&R.

它不是int&x;而不是int * x;因为这就是语言由制造它的人定义的方式 - K&R。

#1


C++ adopts the C syntax. As revealed in "The Development of the C Language" (by Dennis Ritchie) C uses * for pointers in type declarations because it was decided that type syntax should follow use.

C ++采用C语法。正如“C语言的发展”(作者Dennis Ritchie)所揭示的那样,C使用*作为类型声明中的指针,因为决定使用类型语法。

For each object of [a compound type], there was already a way to mention the underlying object: index the array, call the function, use the indirection operator [*] on the pointer. Analogical reasoning led to a declaration syntax for names mirroring that of the expression syntax in which the names typically appear. Thus,

对于[复合类型]的每个对象,已经有一种方法可以提及底层对象:索引数组,调用函数,在指针上使用间接运算符[*]。类比推理导致了一个声明语法,用于反映名称通常出现的表达式语法的名称。从而,

int i, *pi, **ppi;

declare an integer, a pointer to an integer, a pointer to a pointer to an integer. The syntax of these declarations reflects the observation that i, *pi, and **ppi all yield an int type when used in an expression.

声明一个整数,一个指向整数的指针,一个指向整数指针的指针。这些声明的语法反映了在表达式中使用i,* pi和** ppi都会产生int类型的观察结果。

Here's a more complex example:

这是一个更复杂的例子:

int *(*foo)[4][];

This declaration means an expression *(*foo)[4][0] has type int, and from that (and that [] has higher precedence than unary *) you can decode the type: foo is a pointer to an array of size 4 of array of pointers to ints.

这个声明意味着表达式*(* foo)[4] [0]具有int类型,并且从那个(并且[]的优先级高于unary *)你可以解码类型:foo是一个指向大小数组的指针int的指针数组中的4个。

This syntax was adopted in C++ for compatibility with C. Also, don't forget that C++ has a use for & in declarations.

C ++中采用了这种语法,以便与C兼容。另外,不要忘记C ++在声明中有用。

int & b = a;

The above line means a reference variable refering to another variable of type int. The difference between a reference and pointer roughly is that references are initialized only, and you can not change where they point, and finally they are always dereferenced automatically.

上面的行表示引用另一个int类型的变量的引用变量。引用和指针之间的差别大致是引用只是初始化,并且您无法更改它们指向的位置,最后它们总是自动解除引用。

int x = 5, y = 10;
int& r = x;

int sum = r + y; // you do not need to say '*r' automatically dereferenced.

r = y; // WRONG, 'r' can only have one thing pointing at during its life, only at its infancy ;)

#2


I think that Dennis Ritchie answered this in The Development of the C Language:

我认为Dennis Ritchie在C语言的发展中回答了这个问题:

For each object of such a composed type, there was already a way to mention the underlying object: index the array, call the function, use the indirection operator on the pointer. Analogical reasoning led to a declaration syntax for names mirroring that of the expression syntax in which the names typically appear. Thus,

对于这种组合类型的每个对象,已经有一种方法可以提及底层对象:索引数组,调用函数,在指针上使用间接运算符。类比推理导致了一个声明语法,用于反映名称通常出现的表达式语法的名称。从而,

int i, *pi, **ppi;

declare an integer, a pointer to an integer, a pointer to a pointer to an integer. The syntax of these declarations reflects the observation that i, *pi, and **ppi all yield an int type when used in an expression. Similarly,

声明一个整数,一个指向整数的指针,一个指向整数指针的指针。这些声明的语法反映了在表达式中使用i,* pi和** ppi都会产生int类型的观察结果。同样的,

int f(), *f(), (*f)();

declare a function returning an integer, a function returning a pointer to an integer, a pointer to a function returning an integer;

声明一个返回整数的函数,一个返回指向整数的指针的函数,一个返回整数的函数的指针;

int *api[10], (*pai)[10];

declare an array of pointers to integers, and a pointer to an array of integers. In all these cases the declaration of a variable resembles its usage in an expression whose type is the one named at the head of the declaration.

声明一个指向整数的指针数组,以及一个指向整数数组的指针。在所有这些情况下,变量的声明类似于在表达式中的用法,该表达式的类型是在声明的头部命名的类型。

So we use type * var to declare a pointer because this allows the declaration to mirror the usage (dereferencing) of the pointer.

因此我们使用类型* var来声明指针,因为这允许声明镜像指针的使用(解除引用)。

In this article, Ritchie also recounts that in "NB", an extended version of the "B" programming language, he used int pointer[] to declare a pointer to an int, as opposed to int array[10] to declare an array of ints.

在本文中,Ritchie还在“NB”中叙述了“B”编程语​​言的扩展版本,他使用int pointer []来声明一个指向int的指针,而不是int数组[10]来声明一个数组整数。

#3


If you are a visual thinker, it may help to imagine the asterisk as a black hole leading to the data value. Hence, it is a pointer.

如果您是视觉思考者,可能有助于将星号想象为导致数据值的黑洞。因此,它是一个指针。

The ampersand is the opposite end of the hole, think of it as an unraveled asterisk or a spaceship wobbling about in an erratic course as the pilot gets over the transition coming out of the black hole.

&符号是洞的另一端,当飞行员越过从黑洞出来的过渡时,将它想象成一个散开的星号或宇宙飞船在一个不规则的过程中摇摆不定。

I remember being very confused by C++ overloading the meaning of the ampersand, to give us references. In their desperate attempt to avoid using any more characters, which was justified by the international audience using C and known issues with keyboard limitations, they added a major source of confusion.

我记得很担心C ++重载&符号的含义,给我们参考。他们绝望地试图避免使用任何更多角色,这是由国际观众使用C和键盘限制的已知问题所证明的,他们增加了一个混乱的主要来源。

One thing that may help in C++ is to think of references as pre-prepared dereferenced pointers. Rather than using &someVariable when you pass in an argument, you've already used the trailing ampersand when you defined someVariable. Then again, that might just confuse you further!

在C ++中可能有用的一件事是将引用视为预先准备好的解引用指针。传入参数时,不是使用&someVariable,而是在定义someVariable时已经使用了尾随符号。再说一遍,这可能会让你更进一步!

One of my pet hates, which I was unhappy to see promulgated in Apple's Objective-C samples, is the layout style int *someIntPointer instead of int* someIntPointer

我不喜欢看到在Apple的Objective-C示例中发布的一个宠物讨厌的是布局样式int * someIntPointer而不是int * someIntPointer

IMHO, keeping the asterisk with the variable is an old-fashioned C approach emphasizing the mechanics of how you define the variable, over its data type.

恕我直言,用变量保留星号是一种老式的C方法,强调了你如何在数据类型上定义变量的机制。

The data type of someIntPointer is literally a pointer to an integer and the declaration should reflect that. This does lead to the requirement that you declare one variable per line, to avoid subtle bugs such as:

someIntPointer的数据类型实际上是指向整数的指针,声明应该反映出来。这确实导致您要求每行声明一个变量,以避免细微的错误,例如:

int* a, b;  // b is a straight int, was that our intention?

int  *a, *b;  // old-style C declaring two pointers

int* a;
int* b;  // b is another pointer to an int

Whilst people argue that the ability to declare mixed pointers and values on the same line, intentionally, is a powerful feature, I've seen it lead to subtle bugs and confusion.

虽然有人认为有意识地在同一行上声明混合指针和值的能力是一个强大的功能,但我已经看到它会导致细微的错误和混乱。

#4


Your second example is not valid C code, only C++ code. The difference is that one is a pointer, whereas the other is a reference.

你的第二个例子不是有效的C代码,只有C ++代码。区别在于一个是指针,而另一个是参考。

On the right-hand side the '&' always means address-of. In a definition it indicates that the variable is a reference.

在右侧,'&'总是表示地址。在定义中,它表示变量是引用。

On the right-hand side the '*' always means value-at-address. In a definition it indicates that the variable is a pointer.

在右侧,'*'始终表示地址价值。在定义中,它表示变量是指针。

References and pointers are similar, but not the same. This article addresses the differences.

引用和指针类似,但不一样。本文讨论了这些差异。

#5


Instead of reading int* b as "b is a pointer to int", read it as int *b: "*b is an int". Then, you have & as an anti-*: *b is an int. The address of *b is &*b, or just b.

而不是将int * b读作“b是指向int的指针”,而是将其读作int * b:“* b是一个int”。然后,你有&作为反*:* b是一个int。 * b的地址是&* b,或者只是b。

#6


I think the answer may well be "because that's the way K&R did it."

我认为答案很可能是“因为这就是K&R的做法。”

Downvoting fools. Explain why I'm wrong.

愚弄傻瓜。解释为什么我错了。

K&R are the ones who decided what the C syntax for declaring pointers was.

K&R决定用于声明指针的C语法是什么。

It's not int & x; instead of int * x; because that's the way the language was defined by the guys who made it up -- K&R.

它不是int&x;而不是int * x;因为这就是语言由制造它的人定义的方式 - K&R。