Автоматическое целочисленное преобразование значения 0 не выполняется

У меня есть этот исходный файл:

#include <ctime>

class A
{
 public:
 A(unsigned long i){};
 A(const tm*){};
};

int main(int argc, char** argv)
{
 A tit(1);
 A tat(0);
 return 0;
}
</ctime>

Когда я скомпилирую это с помощью gcc 3.4.2, я получаю следующее:

autoCast.cpp: В функции <code>int main(int, char**)': autoCast.cpp:13: error: call of overloaded</code> <code>int main(int, char**)': autoCast.cpp:13: error: call of overloaded</code> <code>int main(int, char**)': autoCast.cpp:13: error: call of overloaded</code> A (int) 'неоднозначен autoCast.cpp: 4: примечание: кандидаты: A :: A (const A &) autoCast.cpp: 7: примечание: A :: A (const tm *) autoCast.cpp: 6: note: A :: A (long unsigned int)

Мой вопрос: почему создание A tit(1) (строка 12) преуспевает, а A tat(0) (строка 13) терпит неудачу? Я пробовал разные типы аргументов в этих строках (например, 0ULL и 1ULL), но он всегда терпит неудачу, когда значение аргумента равно 0, в то время как оно достигает успеха, когда значение аргумента равно 1. Единственное значение 0, для которого не возникает ошибка, равно 0UL (поскольку no требуется преобразование.) Почему в этом случае целое число со значением 0 получает различную обработку от целого числа со значением 1? Имеет ли это отношение к структуре tm, определенной во времени. H?

2 ответа

Это связано с тем, что 0 является константой нулевого указателя и может быть преобразована в unsigned long или указатель, и поэтому она является неоднозначной, которую нужно выбрать. В проекте C++ стандартном разделе 4.10 Преобразования указателя (подчеркивание):

Константа нулевого указателя представляет собой целочисленное константное выражение (5.19) prvalue целочисленного типа, которое вычисляет нуль или значение prtyue типа std :: nullptr_t. <span>Константа нулевого указателя может быть преобразована в тип указателя;</span> <span>результатом является нулевое значение указателя</span> этого типа и отличается от любого другого значения указателя объекта или типа указателя функции.

Хотя 1 не является константой нулевого указателя. Хотя 0UL может быть преобразован в указатель, это лучше подходит для беззнакового длинного конструктора, поскольку преобразование не требуется.


Литерал 0 часто используется для инициализации указателя на нуль (современный C++ должен, по общему признанию, использовать nullptr). Тем не менее, довольно редко можно инициализировать указатели непосредственно с любым другим целым литералом (за исключением, например, встроенных систем, которые используют отображение памяти).

Таким образом, компилятор обрабатывает 0 как если бы он мог быть указателем или целым числом, то есть он мог вызывать либо конструктор. Напротив, он рассматривает 1 просто как целое число.

licensed under cc by-sa 3.0 with attribution.