Небольшая путаница с указателями, инициализация типа данных и объявление нескольких указателей - PullRequest
0 голосов
/ 07 февраля 2020

Когда мы создаем структуру, скажем, для дерева или связанного списка, что-то вроде этого:

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

Каков тип для очереди для хранения узлов структуры? Я думал, что это указатель на структуру.

std::queue<TreeNode*> q;

Но если я попытаюсь инициализировать несколько узлов следующим образом:

TreeNode* l = nullptr, r = nullptr;

Это не сработает, и вам придется сделать

TreeNode *l = nullptr, TreeNode *r = nullptr;

Может кто-нибудь помочь мне понять это немного лучше?

edit: После прочтения этого ответа Объявление нескольких указателей объектов в одной строке вызывает ошибку компилятора Что я понимаю, так это: В обоих C и C ++, * привязывается к декларатору, а не к спецификатору типа. В обоих языках объявления основаны на типах выражений, а не объектов.

Тогда как объявляется очередь такой, какая она есть?

Ответы [ 2 ]

3 голосов
/ 07 февраля 2020

Вторая переменная r не объявлена ​​как указатель, она должна быть:

TreeNode *l = nullptr, *r = nullptr;

TreeNode* - это тип, такой как char или int, но если вы решите в той же строке вы должны использовать оператор косвенного обращения *, чтобы компилятор знал, что переменная Speci c является указателем на объект, а не на объект. Когда вы объявляете это в deque или vector или в другом подобном смысле, вы также должны быть в состоянии определить, являются ли допустимые значения tpyes указателями на объект или объекты, поэтому объявление TreeNode* заключено в angular в скобках.

Если вы думаете об этом, это имеет смысл семантически говоря.

0 голосов
/ 07 февраля 2020

В std::queue<TreeNode*> q; скобки заключают полное имя типа. (Под «именем» я подразумеваю весь декларатор для типа, TreeNode *, а не идентификатор.) При описании типа с помощью декларатора используемая форма выглядит так, как будто полное нормальное объявление с идентификатором имеет свой идентификатор, удаленный. Например, начиная с объявления TreeNode *Placeholder, имя типа: TreeNode *.

В TreeNode* l = nullptr, r = nullptr; нет скобок для группировки * с TreeNode. Согласно грамматике C ++, она сгруппирована с l. Если бы здесь были разрешены скобки, чтобы мы могли написать <TypeNode *> l = nullptr, r = nullptr;, то это могло бы сработать. Проблема здесь такая же, как если бы вы написали - a + b: правила просты: - сгруппирован с a, поэтому выражение -a + b, а не - (a + b).

Вы можете конечно обойти это с typedef TreeNode *TreeNodeP; TreeNodeP l = nullptr, r = nullptr;. Это показывает, что эффекты являются просто результатами структурирования грамматики C ++ - нет никакой внутренней причины, по которой компилятор не может сначала принять любое описание типа, а затем список идентификаторов, которые должны быть объявлены с этим типом, но дизайн грамматики просто не делает поддержите это.

(Одним из следствий этого является ввод в заблуждение записи int* a, поскольку близость токенов в тексте отличается от их близости в грамматике - * ближе к int в тексте, но ближе к a в грамматике, поэтому интервал отправляет неверное сообщение.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...