C++ 在一行上声明多个对象指针会导致编译器错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13618282/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Declaring multiple object pointers on one line causes compiler error
提问by Karthik T
when I do this (in my class)
当我这样做时(在我的课堂上)
public:
Entity()
{
re_sprite_eyes = new sf::Sprite();
re_sprite_hair = new sf::Sprite();
re_sprite_body = new sf::Sprite();
}
private:
sf::Sprite* re_sprite_hair;
sf::Sprite* re_sprite_body;
sf::Sprite* re_sprite_eyes;
Everything works fine. However, if I change the declarations to this:
一切正常。但是,如果我将声明更改为:
private:
sf::Sprite* re_sprite_hair, re_sprite_body, re_sprite_eyes;
I get this compiler error:
我收到此编译器错误:
error: no match for 'operator=' in '((Entity*)this)->Entity::re_sprite_eyes = (operator new(272u), (<statement>, ((sf::Sprite*)<anonymous>)))
And then it says candidates for re_sprite_eyes
are sf::Sprite
objects and/or references.
然后它说候选对象re_sprite_eyes
是sf::Sprite
对象和/或引用。
Why does this not work? Aren't the declarations the same?
为什么这不起作用?声明不一样吗?
回答by Karthik T
sf::Sprite* re_sprite_hair, re_sprite_body, re_sprite_eyes;
sf::Sprite* re_sprite_hair, re_sprite_body, re_sprite_eyes;
Does not declare 3 pointers - it is one pointer and 2 objects.
不声明 3 个指针 - 它是一个指针和 2 个对象。
sf::Sprite*
unfortunately does not apply to all the variables declared following it, just the first. It is equivalent to
sf::Sprite*
不幸的是,不适用于在它之后声明的所有变量,仅适用于第一个。它相当于
sf::Sprite* re_sprite_hair;
sf::Sprite re_sprite_body;
sf::Sprite re_sprite_eyes;
You want to do:
你想做:
sf::Sprite *re_sprite_hair, *re_sprite_body, *re_sprite_eyes;
sf::Sprite *re_sprite_hair, *re_sprite_body, *re_sprite_eyes;
You need to put one star for each variable. In such cases I prefer to keep the star on the variable's side, rather than the type, to make exactly this situation clear.
您需要为每个变量打一颗星。在这种情况下,我更喜欢将星号保留在变量一侧,而不是类型,以明确这种情况。
回答by John Bode
In both C and C++, the *
binds to the declarator, not the type specifier. In both languages, declarations are based on the types of expressions, not objects.
在 C 和 C++ 中,*
绑定到declarator,而不是类型说明符。在这两种语言中,声明都是基于表达式的类型,而不是对象。
For example, suppose you have a pointer to an int
named p
, and you want to access the int
value that p
points to; you do so by dereferencing the pointer with the unary *
operator, like so:
例如,假设您有一个指向int
named的指针p
,并且您想访问int
它所p
指向的 值;您可以通过使用一元运算*
符取消引用指针来实现,如下所示:
x = *p;
The type of the expression*p
is int
; thus, the declaration of p
is
表达式的类型*p
是int
; 因此,声明p
是
int *p;
This is true no matter how many pointers you declare within the same declaration statement; if q
and r
also need to be declared as pointers, then they also need to have the unary *
as part of the declarator:
无论您在同一声明语句中声明多少个指针,这都是正确的;如果q
并且r
还需要声明为指针,那么它们还需要将一元*
作为声明符的一部分:
int *p, *q, *r;
because the expressions*q
and *r
have type int
. It's an accident of C and C++ syntax that you can write T *p
, T* p
, or T * p
; all of those declarations will be interpreted as T (*p)
.
因为表达式*q
和*r
具有类型int
。您可以编写T *p
, T* p
, 或T * p
;这是 C 和 C++ 语法的意外。所有这些声明都将被解释为T (*p)
.
This is why I'm not fond of the C++ style of declaring pointer and reference types as
这就是为什么我不喜欢将指针和引用类型声明为 C++ 风格的原因
T* p;
T& r;
because it implies an incorrect view of how C and C++ declaration syntax works, leading to the exactkind of confusion that you just experienced. However, I've written enough C++ to realize that there are times when that style doesmake the intent of the code clearer, especially when defining container types.
因为它暗示了对 C 和 C++ 声明语法如何工作的错误看法,导致您刚刚经历的那种确切的混乱。但是,我已经编写了足够多的 C++ 以意识到有时这种风格确实使代码的意图更加清晰,尤其是在定义容器类型时。
But it's still wrong.
但它仍然是错误的。
回答by rici
In C++11 you have a nice little workaround, which might be better than shifting spaces back and forth:
在 C++11 中,您有一个不错的小解决方法,这可能比来回移动空格更好:
template<typename T> using type=T;
template<typename T> using func=T*;
// I don't like this style, but type<int*> i, j; works ok
type<int*> i = new int{3},
j = new int{4};
// But this one, imho, is much more readable than int(*f)(int, int) = ...
func<int(int, int)> f = [](int x, int y){return x + y;},
g = [](int x, int y){return x - y;};
回答by Robin Nag
Another thing that may call your attention is the line:
int * p1, * p2;
This declares the two pointers used in the previous example. But notice that there is an asterisk (
*
) for each pointer, in order for both to have typeint*
(pointer to int). This is required due to the precedence rules. Note that if, instead, the code was:int * p1, p2;
p1
would indeed be of typeint*
, butp2
would be of typeint
. Spaces do not matter at all for this purpose. But anyway, simply remembering to put one asterisk per pointer is enough for most pointer users interested in declaring multiple pointers per statement. Or even better: use a different statemet for each variable.
另一件可能引起您注意的事情是:
int * p1, * p2;
这声明了前一个示例中使用的两个指针。但请注意,
*
每个指针都有一个星号 ( ),以便两者都有类型int*
(指向 int 的指针)。由于优先规则,这是必需的。请注意,如果代码是:int * p1, p2;
p1
确实是 typeint*
,但p2
会是 typeint
。为此,空格根本无关紧要。但无论如何,对于大多数对每个语句声明多个指针感兴趣的指针用户来说,只需记住为每个指针放置一个星号就足够了。或者甚至更好:为每个变量使用不同的 statemet。
回答by Jive Dadson
The asterisk binds to the pointer-variable name. The way to remember this is to notice that in C/C++, declarations mimic usage.
星号绑定到指针变量名称。记住这一点的方法是注意在 C/C++ 中,声明模仿用法。
The pointers might be used like this:
指针可以这样使用:
sf::Sprite *re_sprite_body;
// ...
sf::Sprite sprite_bod = *re_sprite_body;
Similarly,
相似地,
char *foo[3];
// ...
char fooch = *foo[1];
In both cases, there is an underlying type-specifier, and the operator or operators required to "get to" an object of that type in an expression.
在这两种情况下,都有一个底层类型说明符,以及在表达式中“到达”该类型对象所需的一个或多个运算符。