Подтвердить что ты не робот

Изначальная нулевая инициализация с g++

Я столкнулся с странным поведением следующего кода, играя с инициализацией int с помощью g++ 4.4.3.

  int main()

    {

        int x(int());

        int y = int();

        cout << x << "  " << y <<  endl;
    }

результат:

1 0

Значение "y" равно 0, как ожидалось, но значение x странно "1"!

В VS2008 приведена следующая ошибка ссылки (объявление функции, но без определения):

unresolved external symbol "int __cdecl x(int (__cdecl*)(void))"

Может ли кто-нибудь объяснить это странное поведение g++?

4b9b3361

Ответ 1

Чтобы дополнить ответ GMan здесь (x - это определение функции), почему 1.

Причиной вывода 1 является то, что в месте вызова std::cout << x функция распадается на указатель на функцию (язык не позволяет передавать функции в качестве аргументов другим функциям, поэтому как и с массивами, выполняется неявное преобразование в указатель-к). Теперь нет перегрузки ostream, которая принимает указатель на функцию, и компилятор пытается выбрать преобразование в любую из доступных перегрузок. В этот момент он находит, что лучшая последовательность преобразования равна bool, и она печатает 1 (указатель не равен 0).

Вы можете проверить это, изменив поведение, вы можете использовать std::cout << std::boolalpha << x, и он будет печатать true вместо 1. Кроме того, интересно отметить, что VS является правильным с этим, так как выражение std::cout << x требует ввода адреса x, тогда функция используется, и программа плохо сформирована, если нет определения для этой функции, Вы можете снова проверить это, предоставив определение:

int f() {}
int main() {
   int x(int());      // 1
   x( &f );           // 2
}
int x( int(*)() ) {   // 3
   std::cout << "In x" << std::endl;
}

Где я вручную выполнил преобразование из function в pointer-to-function в определение x (1), а вызов с аргументом f (2) - отметьте, что объявление в 1 и определение в 3 является одной и той же сигнатурой и что & in x( &f ) будет выполняться компилятором, если вы этого не сделаете.

Ответ 2

int x(int()); анализируется как объявление функции.

Он объявляет функцию с именем x, возвращая int и принимающий один параметр, который имеет тип функции, возвращающей int и не принимающий аргументов.

Это называется самым неприятным анализом.

Ответ 3

Просто добавьте больше parens:

int main()

    {

        int x((int()));

        int y = int();

        cout << x << "  " << y <<  endl;
    }

Теперь x - это int, а не функция.

Ответ 4

Как говорили другие, x - это объявление функции. Поскольку для типов указателей функций не существует предопределенного встраивания ostream, g++, похоже, использует неявное преобразование bool (используемое для проверки, является ли указатель функции NULL), чтобы найти способ его вывода.

Visual С++, с другой стороны, жалуется, что объявленная функция x никогда не определена и, следовательно, не может завершить связь. Я подозреваю, что g++ в этом случае достаточно умен, чтобы видеть, что функция никогда не вызывается, и поэтому не беспокоится о ссылке.

Вы можете попробовать добавить фиктивное определение функции int x(int(*)()) { return 0xdeadbeef; } к коду и посмотреть, что с ним делает MSVC.

Ответ 5

С++ интерпретирует первый как объявление функции.

Ответ 6

Это

int x(int());

Является фактически объявлением функции, вход является функцией следующей подписи

int fn(void)

Указатель функции, переданный в std::cout <<, преобразуется в bool (1), поскольку это не-NULL-указатель.