Как я могу инициализировать указатель типа *, используя синтаксис типа()?

Переменные встроенных типов могут быть инициализированы по значению следующим образом:

int var = int();

таким образом, я получаю значение по умолчанию int без жесткого кодирования нуля в моем коде.

Однако, если я попытаюсь сделать подобный материал для указателя:

int* ptr = int*();

компилятор (Visual С++ 10) отказывается компилировать это (говорит type int unexpected).

Как мне инициализировать указатель таким же образом?

Ответ 1

Как мне инициализировать указатель Type * с помощью синтаксиса типа()?

Вы не можете. Синтаксис T() определяется в 5.2.3/1,2 (С++ 03, немного другая формулировка в С++ 11 FDIS). В частности, во втором абзаце говорится:

Выражение T(), где T является спецификатором простого типа (7.1.5.2) для типа объекта без массива или типа (void cv-qualified) void, создает rvalue указанного типа, который инициализируется значением (8.5);

Это означает, что int(), создаст rvalue типа int и значение-инициализирует его. Теперь проблема заключается в том, что int* не является спецификатором простого типа, а скорее специфицированным спецификатором типа. Определение спецификатора простого типа в грамматике:

  simple-type-specifier:
    ::opt nested-name-specifieropt type-name
    ::opt nested-name-specifier template template-id
    char
    wchar_t
    bool
    short
    int
    long
    signed
    unsigned
    float
    double
    void

С именем типа определяется как:

  type-name:
    class-name
    enum-name
    typedef-name

Это то, что заставляет предлагаемые решения работать. Создание typedef (либо напрямую, либо через шаблон) создает имя типа (третий тип), которое может использоваться как спецификатор простого типа (первый тип).

Ответ 2

Используйте typedef для создания имени для вашего типа указателя:

typedef int *ip;

ip ptr = ip();

Такая же идея должна работать для других типов, для которых требуется более одного лексического элемента (слова) для определения имени типа (например, unsigned long, long long, unsigned long long * и т.д.).

Ответ 3

Не требуется использование typedef (но исключительно для С++ 11), что может быть полезно при работе с несколькими типами указателей:

template<typename T>
using alias = T;

тогда alias<int*> есть int*, поэтому вы можете сделать int* p = alias<int*>().

Аналогичное решение, доступное для С++ 03, с использованием метаданных идентификации:

template<typename T>
struct identity {
    typedef T type;
};

int* p = identity<int*>::type();

Ответ 4

Просто сделай

int* x = int();

Он по-прежнему присваивает 0 указателю, заставляя его указывать на NULL-адрес, поскольку вы по умолчанию его используете со значением по умолчанию, которое равно 0.

На самом деле, он отлично работает для всех типов:

double* y = int();

Адрес по-прежнему является 32-разрядным (или 64-битным в зависимости от платформы) целым числом, поэтому я думаю, что он должен работать нормально для всех типов, если вы делаете = int().

Ответ 5

Здесь один из способов:

template <typename T>
T make_default()
{
    return T();
}

int main()
{
    int *p = make_default<int*>();
}

Ответ 6

Причина, по которой это не работает, заключается в том, что указатели не имеют конструкторов.

Синтаксис

int ()

вызывает (теоретически)

int::int ()

который инициализирует переменную. (Скорее всего, компилятор просто нули переменную, но это потому, что он "знает" о ints).

В С++ 11 вы можете использовать nullptr

int *ptr = nullptr;

В противном случае вам в значительной степени придется использовать NULL:

int *ptr = NULL;