Как я могу инициализировать указатель типа *, используя синтаксис типа()?
Переменные встроенных типов могут быть инициализированы по значению следующим образом:
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;
Ответ 7
Вот как вы это делаете int * ptr = new int;
Указатели кучи