Когда использовать Q_NULLPTR?

Я вижу, что Q_NULLPTR используется либерально в исходном коде Qt и примерах, но я не нашел никакой документации о том, что именно и когда она должна использоваться.

Например, в этой официальной демонстрации нового модуля Qt SerialBus, добавленного в новый Qt v5.6:

if (!m_canDevice->connectDevice()) {
    delete m_canDevice;
    m_canDevice = Q_NULLPTR;

Это послужило цели nullptr до того, что было добавлено в С++ 11? Если да, то теперь, когда у нас есть С++ 11, следует ли использовать Q_NULLPTR?

PS: Я попытался найти исходный код Qt для определения макроса, но не смог его найти.

Ответ 1

Это послужило цели nullptr до того, что было добавлено в C++ 11? Если да, то теперь, когда у нас есть C++ 11, следует ли использовать Q_NULLPTR?

Да (несколько) и Нет соответственно.

C++ не хватало еще в те дни, поэтому у Qt были свои вещи, которые позже стали устаревшими, поскольку C++ догнал функции.

При этом Q_NULLPTR является (не) функционально таким же, как nullptr (как заметил Андрей, если C++ 11 поддерживается, он расширяется до nullptr), он не дает вам типа безопасности, просто синтаксис "сахар". Он проиллюстрировал намерение человека, читающего код, а не компилятору как nullptr.

Ответ 2

Q_NULLPTR - это макрос, который заменяется как nullptr если компилятор поддерживает С++ 11 и как NULL (который заменяется на 0), если это не так. Если вы используете С++ 11, вместо этого вы можете написать nullptr; используйте NULL если вы этого не сделаете.

Ответ 3

Используйте Q_NULLPTR чтобы оставаться независимым от компилятора.

Если теперь вы решите использовать nullptr, ваш код не будет компилироваться с более старым компилятором С++ 98. Если вы решите использовать NULL, вы потеряете безопасность типа С++ 11, даже если она доступна в вашем текущем компиляторе.

По той же причине существуют макросы, такие как qMove(x) и соответствующее определение Q_COMPILER_RVALUE_REFS.

Ответ 4

Фактически у Q_NULLPTR была только одна цель: разрешить использование nullptr без потери поддержки для компиляторов, у которых не было поддержки С++ 11/С++ 0x, поскольку прямое использование nullptr приведет к ошибкам в таких настройках. Недостатком является то, что существуют двусмысленности его отказа от NULL (или 0 в более старых версиях Qt), что может привести к непреднамеренному поведению в режиме исполнения и ограничить поддерживаемые варианты использования по сравнению с nullptr.

В редком случае, когда вы нацеливаете компиляторы, отличные от С++ 11, используйте Q_NULLPTR но убедитесь, что код работает хорошо, когда функции С++ 11 отключены. Во всех остальных ситуациях nullptr является лучшей альтернативой, так как это приводит к ошибкам компиляции вместо ошибочного поведения во время выполнения при использовании с устаревшими компиляторами. Qt 5.7 и позже опустили поддержку для компиляции без С++ 11, поэтому нет необходимости в Q_NULLPTR если вы Q_NULLPTR от этих версий.

Существуют и другие функции, такие как qMove или Q_DECL_OVERRIDE которые дают улучшенную семантику при использовании для поддержки компиляторов без разбивки компиляции на старых компиляторах.