new
оператор (C++)
Пытается выделить и инициализировать объект или массив объектов указанного или заполнителя и возвращает подходящий типизированный ненулевой указатель на объект (или начальный объект массива).
Синтаксис
new-expression
:
::
optnew
new-placement
optnew-type-id
new-initializer
opt
::
optnew
new-placement
opt(
type-id
)
new-initializer
opt
new-placement
:
(
expression-list
)
new-type-id
:
type-specifier-seq
new-declarator
необ.
new-declarator
:
ptr-operator
new-declarator
необ.
noptr-new-declarator
noptr-new-declarator
:
[
expression
]
attribute-specifier-seq
необ.
noptr-new-declarator
[
constant-expression
]
attribute-specifier-seq
необ.
new-initializer
:
(
expression-list
необ.)
braced-init-list
Замечания
Если ошибка, new
возвращается ноль или вызывает исключение. Дополнительные сведения см. в разделе "Операторы" и delete
"new
Операторы". Это поведение по умолчанию можно изменить, написав настраиваемую подпрограмму обработки исключений и вызвав _set_new_handler
функцию библиотеки времени выполнения с именем функции в качестве аргумента.
Сведения о создании объекта в управляемой куче в C++/CLI и C++/CX см . в разделе gcnew.
Примечание.
Расширения компонентов Microsoft C++ (C++/CX) обеспечивают поддержку new
ключевое слово добавления записей слотов vtable. Дополнительные сведения см. в разделе new
(новый слот в vtable)
Если new
используется для выделения памяти для объекта класса C++, конструктор объекта вызывается после выделения памяти.
delete
Используйте оператор, чтобы освободить память, выделенную операторомnew
. delete[]
Используйте оператор для удаления массива, выделенного операторомnew
.
В следующем примере выделяется и затем освобождается двумерный массив символов размером dim
на 10. При выделении многомерного массива все измерения, кроме первого, должны быть константными выражениями, которые оцениваются положительными значениями. Самое левое измерение массива может быть любым выражением, которое оценивается положительным значением. При выделении массива new
с помощью оператора первое измерение может быть равно нулю; new
оператор возвращает уникальный указатель.
char (*pchar)[10] = new char[dim][10];
delete [] pchar;
Не type-id
удается содержать const
, volatile
объявления классов или объявления перечисления. Следующее выражение является плохо сформированным:
volatile char *vch = new volatile char[20];
Оператор new
не выделяет ссылочные типы, так как они не объекты.
Оператор new
не может использоваться для выделения функции, но его можно использовать для выделения указателей на функции. В следующем примере выделяется и затем освобождается массив из семи указателей на функции, которые возвращают целые числа.
int (**p) () = new (int (*[7]) ());
delete p;
Если оператор new
используется без дополнительных аргументов и компилируется с /GX
параметром , /EHa
или /EHs
параметром, компилятор создает код для вызова оператора delete
, если конструктор создает исключение.
В следующем списке описываются элементы грамматики new
:
new-placement
Предоставляет способ передачи дополнительных аргументов при перегрузке new
.
type-id
Указывает тип, который нужно выделить; это может быть встроенный или определяемый пользователем тип. Если спецификация типа является сложной, она может быть окружена круглыми скобками, чтобы принудительно реализовать порядок привязки. Тип может быть заполнителем (auto
), тип которого определяется компилятором.
new-initializer
Предоставляет значение для инициализированного объекта. Инициализаторы не могут быть указаны для массивов. Оператор new
создаст массивы объектов только в том случае, если класс имеет конструктор по умолчанию.
noptr-new-declarator
Задает границы массива. При выделении многомерного массива все измерения, кроме первого, должны быть константными выражениями, которые оцениваются в положительные значения, преобразуемые std::size_t
в . Самое левое измерение массива может быть любым выражением, которое оценивается положительным значением. Применяется attribute-specifier-seq
к связанному типу массива.
Пример. Выделение и освобождение массива символов
В следующем примере кода выделяется и освобождается массив символов и объект класса CName
.
// expre_new_Operator.cpp
// compile with: /EHsc
#include <string.h>
class CName {
public:
enum {
sizeOfBuffer = 256
};
char m_szFirst[sizeOfBuffer];
char m_szLast[sizeOfBuffer];
public:
void SetName(char* pszFirst, char* pszLast) {
strcpy_s(m_szFirst, sizeOfBuffer, pszFirst);
strcpy_s(m_szLast, sizeOfBuffer, pszLast);
}
};
int main() {
// Allocate memory for the array
char* pCharArray = new char[CName::sizeOfBuffer];
strcpy_s(pCharArray, CName::sizeOfBuffer, "Array of characters");
// Deallocate memory for the array
delete [] pCharArray;
pCharArray = NULL;
// Allocate memory for the object
CName* pName = new CName;
pName->SetName("Firstname", "Lastname");
// Deallocate memory for the object
delete pName;
pName = NULL;
}
Пример: new
оператор
Если используется форма размещения оператора (форма с большим количеством аргументов, чем размер), компилятор не поддерживает форму new
delete
размещения оператора, если конструктор создает исключение. Например:
// expre_new_Operator2.cpp
// C2660 expected
class A {
public:
A(int) { throw "Fail!"; }
};
void F(void) {
try {
// heap memory pointed to by pa1 will be deallocated
// by calling ::operator delete(void*).
A* pa1 = new A(10);
} catch (...) {
}
try {
// This will call ::operator new(size_t, char*, int).
// When A::A(int) does a throw, we should call
// ::operator delete(void*, char*, int) to deallocate
// the memory pointed to by pa2. Since
// ::operator delete(void*, char*, int) has not been implemented,
// memory will be leaked when the deallocation can't occur.
A* pa2 = new(__FILE__, __LINE__) A(20);
} catch (...) {
}
}
int main() {
A a;
}
Инициализация объектов, выделенных с помощью new
Необязательное new-initializer
поле включается в грамматику для new
оператора. Это поле позволяет инициализировать новые объекты с помощью определяемых пользователем конструкторов. Дополнительные сведения о том, как выполняется инициализация, см. в разделе "Инициализаторы". В следующем примере показано, как использовать выражение инициализации с оператором new
:
// expre_Initializing_Objects_Allocated_with_new.cpp
class Acct
{
public:
// Define default constructor and a constructor that accepts
// an initial balance.
Acct() { balance = 0.0; }
Acct( double init_balance ) { balance = init_balance; }
private:
double balance;
};
int main()
{
Acct *CheckingAcct = new Acct;
Acct *SavingsAcct = new Acct ( 34.98 );
double *HowMuch = new double { 43.0 };
// ...
}
В этом примере объект CheckingAcct
выделяется с помощью new
оператора, но инициализация по умолчанию не указана. Поэтому вызывается конструктор по умолчанию для класса Acct()
. Затем объект SavingsAcct
выделяется таким же образом, за исключением того, что он явно инициализирован до 34,98. Так как 34.98 имеет тип double
, конструктор, принимаюющий аргумент этого типа, вызывается для обработки инициализации. Наконец, тип HowMuch
, отличный от класса, инициализирован до 43.0.
Если объект имеет тип класса и этот класс имеет конструкторы (как и в предыдущем примере), объект можно инициализировать оператором new
, только если выполняется одно из этих условий:
Аргументы, предоставленные в инициализаторе, соответствуют аргументам конструктора.
Класс имеет конструктор по умолчанию (конструктор, который можно вызвать без аргументов).
Явное инициализация для каждого элемента не может выполняться при выделении массивов с помощью new
оператора; вызывается только конструктор по умолчанию, если он присутствует. Дополнительные сведения см. в разделе "Аргументы по умолчанию".
Если выделение памяти завершается сбоем (operator new
возвращает значение 0), инициализация не выполняется. Это поведение защищает от попыток инициализации данных, которые не существуют.
Как и при вызовах функций, порядок вычисления инициализированных выражений не определен. Кроме того, вы не должны полагаться на эти выражения, которые оцениваются полностью перед выделением памяти. Если выделение памяти завершается ошибкой, а new
оператор возвращает ноль, некоторые выражения в инициализаторе могут не оцениваться полностью.
Время существования объектов, выделенных с помощью new
Объекты, выделенные операторомnew
, не уничтожаются при выходе область, в которой они определены. new
Так как оператор возвращает указатель на выделенные объекты, программа должна определить указатель с подходящим область для доступа к этим объектам и удаления этих объектов. Например:
// expre_Lifetime_of_Objects_Allocated_with_new.cpp
// C2541 expected
int main()
{
// Use new operator to allocate an array of 20 characters.
char *AnArray = new char[20];
for( int i = 0; i < 20; ++i )
{
// On the first iteration of the loop, allocate
// another array of 20 characters.
if( i == 0 )
{
char *AnotherArray = new char[20];
}
}
delete [] AnotherArray; // Error: pointer out of scope.
delete [] AnArray; // OK: pointer still in scope.
}
После того как указатель AnotherArray
в этом примере вышел за пределы области видимости, объект невозможно удалить.
Как работает new
Выражение new-expression
, new
содержащее оператор, выполняет три действия:
Находит и резервирует хранилище для объекта или объектов, которым нужно выделить память. По завершении этого этапа выделяется правильный объем хранилища, но он еще не является объектом.
Инициализирует объекты. После завершения инициализации имеется достаточно информации, чтобы выделенная память являлась объектом.
Возвращает указатель на объекты типа указателя, производные от
new-type-id
илиtype-id
. Программа использует этот указатель для доступа к новому объекту, которому выделена память.
Оператор new
вызывает функцию operator new
. Для массивов любого типа и для объектов, которые не class
являются , struct
или union
типами, глобальной функцией, ::operator new
вызывается для выделения хранилища. Объекты типа класса могут определять собственную operator new
статическую функцию-член на основе каждого класса.
Когда компилятор обнаруживает new
оператор для выделения объекта типаT
, он выдает вызов T::operator new( sizeof(T) )
или, если пользователь не определенoperator new
. ::operator new( sizeof(T) )
Это то, как new
оператор может выделить правильный объем памяти для объекта.
Примечание.
Аргумент operator new
типа std::size_t
. Этот тип определяется в <direct.h>, <malloc.h, <memory.h>, search.h>><, <stddef.h>, <stdio.h>, stdlib.h>, <<string.h> и <time.h.>
Параметр в грамматике разрешает спецификацию new-placement
(см. грамматику оператораnew
). Параметр new-placement
можно использовать только для определяемых пользователем реализаций operator new
; он позволяет передавать operator new
дополнительные сведения. Выражение с таким полем new-placement
, как T *TObject = new ( 0x0040 ) T;
преобразование T *TObject = T::operator new( sizeof( T ), 0x0040 );
в значение, в которое входит operator new
класс T, в противном случае — в T *TObject = ::operator new( sizeof( T ), 0x0040 );
.
Первоначальное new-placement
намерение поля заключается в том, чтобы разрешить аппаратным зависимым объектам выделяться по указанным пользователем адресам.
Примечание.
Хотя в предыдущем примере показано только один аргумент в new-placement
поле, нет ограничений на то, сколько дополнительных аргументов можно передать таким operator new
образом.
Даже если operator new
для типа T
класса определен тип класса, можно явно использовать глобальный оператор new
, как в следующем примере:
T *TObject = ::new TObject;
Оператор область разрешения (::
) принудительно использует глобальный new
оператор.
См. также
Выражения с унарными операторами
Ключевые слова
new
операторы и delete
операторы
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделе:Отправить и просмотреть отзыв по