Reputation: 240
When we make a structure for let's say a tree or a linked list, something of this nature:
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
What is the type for queue to store nodes of the structure? I thought it was a pointer to the struct.
std::queue<TreeNode*> q;
But if I try to initialize multiple nodes like this:
TreeNode* l = nullptr, r = nullptr;
It doesn't work and you have to do
TreeNode *l = nullptr, TreeNode *r = nullptr;
Can someone help me understand this a little better?
edit: After reading this answer Declaring multiple object pointers on one line causes compiler error What I'm understanding is that: 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.
Then how is the queue declared the way it is?
Upvotes: 0
Views: 172
Reputation: 23832
The second variable r
is not declared as a pointer, it should be:
TreeNode *l = nullptr, *r = nullptr;
TreeNode*
is a type, like a char
or int
, but if you delclare it in the same line you must use the *
indirection operator so that the compiler knows that the specific variable is a pointer to object, not an object. When you declare it in a deque
or a vector
or somenthing like that, you must also be able to tell if the tpyes admitted are pointers to object or objects, hence the declaration TreeNode*
inside angular brackets.
If you think about it, it makes sense semantically speaking.
Upvotes: 3
Reputation: 224102
In std::queue<TreeNode*> q;
, the brackets enclose a complete type name. (By “name,” I mean the entire declarator for the type, TreeNode *
, not an identifier.) When describing a type with a declarator, the form used is as if a complete normal declaration with an identifier had its identifier removed. For example, starting with a declaration TreeNode *Placeholder
, the type name is TreeNode *
.
In TreeNode* l = nullptr, r = nullptr;
, there are no brackets to group the *
with TreeNode
. According to the C++ grammar, it is grouped with l
. If brackets were allowed here, so that we could write <TypeNode *> l = nullptr, r = nullptr;
, then that could work. The issue here is the same as if you write - a + b
: The rules are simply that -
is grouped with a
, so the expression is -a + b
, not - (a + b)
.
You can of course work around this with typedef TreeNode *TreeNodeP; TreeNodeP l = nullptr, r = nullptr;
. This shows the effects are simply the results of how the C++ grammar is structured—there is no inherent reason a compiler could not accept any type description first and then a list of identifiers to be declared with that type, but the grammar design simply does not support that.
(One consequence of this is that it is misleading to write int* a
, because the proximity of tokens in the text is different from their proximity in the grammar—*
is closer to int
in the text but is closer to a
in the grammar, so the spacing sends the wrong message.)
Upvotes: 0