Я изучаю С++. Следующая программа выглядит красиво и универсально:
typedef some_type T;
int main() {
T* p = new T;
}
И это действительно работает для типов, не являющихся массивами, таких как int
и т. д. Однако, если я попробую typedef int T[2];
, он сломается с ошибкой:
невозможно преобразовать 'int*' в 'int (*)[2]'.
Какая здесь логика? Могу ли я что-нибудь сделать, чтобы new
возвращал объект правильного (для этого указателя) типа?
typedef int T[2];
int main() {
T* p = new ???;
}
Кстати, new int[2]
тоже не работает. Возможно, мне здесь не хватает какого-то синтаксиса, общая идея заключалась бы в том, чтобы выделить объект типа T, где тип T представляет собой массив из двух целых чисел.
Примечание: обычно лучше использовать std::array
для необработанного массива C. Создание псевдонимов типов также проще.
Могу ли я что-нибудь сделать с new, чтобы он возвращал объект правильного (для этого указателя) типа? Ответ: T* p = new int[1][2];
Или, если вы не знаете размер до момента выполнения (скажем, размер зависит от данных, считываемых во время работы программы), используйте контейнер с изменяемым размером, например std::vector
. По сути, лучше избегать массивов в стиле C (и прямого использования любого выражения new
).
Лучше использовать интеллектуальные указатели и массив или вектор вместо указателя и массива в стиле C, потому что вам нужно позаботиться об управлении памятью.
@Mahdy.n даже с умными указателями вы должны использовать правильный синтаксис для new
. И vector
здесь неуместно, поскольку им нужен только один экземпляр T
.
@MarkRansom конечно, но если он использует указатель на vector
с unique_ptr<vector<int>>
или array
, то ему не нужно использовать new
и delete
.
@Mahdy.n как инициализировать unique_ptr
без new
? Это была моя точка зрения.
@MarkRansom У меня, конечно, не так много опыта разработки, как у тебя, но стоит ли нам использовать NEW? Я так не думаю, мы можем создать уникальный указатель на вектор, например: using T = int;
для любого типа данных и std:: vector<T> vec(size);
и указатель ` auto vec_ptr = std::make_unique<std::vector<T>>(vec);` и чем использовать указатель.
@MarkRansom, ты прав, даже с unique_ptr
где-то прячется new
. Но (1) вы можете использовать make_unique
, чтобы полностью очистить свой код от явных new
(2) вам не нужно беспокоиться о ручных delete
. Может быть, я неправильно понял твое намерение, но ты не согласен, что так все же лучше?
@wohlstad да, я согласен, что исключение нового/удаления - это хорошо, локальная переменная - лучшее, если вам это сойдет с рук. Но поскольку речь идет о new
, весь этот побочный стеб просто отвлекает.
@MarkRansom, поскольку ОП упомянул, что они изучают C++, я подумал, что это может быть полезно (помимо решения конкретной проблемы). Как вы сказали, локальная переменная была бы лучше, если бы она применима, и я также упомянул об этом в своем ответе ниже.
Возможно, мне не хватает синтаксиса здесь
Прежде всего обратите внимание, что T*
на самом деле является int(*)[2]
.
Теперь здесь есть два варианта/ответа:
Один допустимый синтаксис:
T* p = new int[2][2];
Или другой эквивалентный допустимый синтаксис:
T* p = new T[2]; //this is also valid in c++
Кстати, вам следует использовать std::array
и умные указатели в современном C++.
Другой ответ уже дал решение вашей насущной проблемы.
Но поскольку вы упомянули, что изучаете C++, ниже вы можете найти несколько рекомендаций:
Как уже упоминалось, рекомендуется отдавать предпочтение std::array необработанным массивам C (или std::vector для массивов динамического размера).
Используйте указатели только в том случае, если они вам действительно нужны. Во многих случаях лучше использовать объекты «по значению» (и это должно быть по умолчанию).
Если вам необходимо использовать указатель, отдайте предпочтение умным указателям вместо необработанных указателей C. Они будут автоматически управлять сроком существования объекта (когда вы используете new
, вы должны не забыть сопоставить его с delete
).
Вот краткий пример:
#include <memory>
#include <array>
// T is an alias for the type of std::array<int,2>:
using T = std::array<int,2>;
int main() {
// a is an object of type std::array<int,2>:
T a;
// p is a unique_ptr to std::array<int,2>:
std::unique_ptr<T> p = std::make_unique<T>();
}
Обратите внимание на использование псевдонима типа вместо typedef
в современном C++.
T*
на самом делеint(*)[2]
. Таким образом, правильный синтаксис будетT* p = new T[2];
.