new
operator (C++)
Próbuje przydzielić i zainicjować obiekt lub tablicę obiektów określonego lub zastępczego typu i zwraca odpowiednio wpisany wskaźnik niezerowy do obiektu (lub do początkowego obiektu tablicy).
Składnia
new-expression
:
::
opt opt new
new-placement
new-type-id
new-initializer
::
opt opt new
new-placement
(
type-id
)
new-initializer
new-placement
:
(
expression-list
)
new-type-id
:
type-specifier-seq
new-declarator
Zdecydować
new-declarator
:
ptr-operator
new-declarator
Zdecydować
noptr-new-declarator
noptr-new-declarator
:
[
expression
]
attribute-specifier-seq
Zdecydować
noptr-new-declarator
[
constant-expression
]
attribute-specifier-seq
Zdecydować
new-initializer
:
(
expression-list
Zdecydować )
braced-init-list
Uwagi
Jeśli błąd nie powiedzie się, new
zwraca zero lub zgłasza wyjątek. Aby uzyskać więcej informacji, zobacz Operatorynew
i delete
. To domyślne zachowanie można zmienić, pisząc niestandardową procedurę obsługi wyjątków i wywołując _set_new_handler
funkcję biblioteki czasu wykonywania z nazwą funkcji jako jej argumentem.
Aby uzyskać informacje na temat tworzenia obiektu na zarządzanym stercie w języku C++/CLI i C++/CX, zobacz gcnew.
Uwaga
Rozszerzenia składników języka Microsoft C++ (C++/CX) zapewniają obsługę słowa kluczowego służącego new
do dodawania wpisów gniazda tabeli wirtualnej. Aby uzyskać więcej informacji, zobacz new
(nowe miejsce w tabeli wirtualnej)
Gdy new
jest używana do przydzielania pamięci dla obiektu klasy C++, konstruktor obiektu jest wywoływany po przydzieleniu pamięci.
Użyj operatora , delete
aby cofnąć przydział pamięci przydzielonej new
przez operatora. delete[]
Użyj operatora , aby usunąć tablicę przydzieloną new
przez operatora.
Poniższy przykład przydziela, a następnie zwalnia dwuwymiarową tablicę znaków o rozmiarze dim
10. Podczas przydzielania tablicy wielowymiarowej wszystkie wymiary z wyjątkiem pierwszego muszą być wyrażeniami stałymi, które oceniają wartości dodatnie. Najbardziej lewy wymiar tablicy może być dowolnym wyrażeniem, które daje wartość dodatnią. Podczas przydzielania tablicy przy użyciu new
operatora pierwszy wymiar może być zerowy; new
operator zwraca unikatowy wskaźnik.
char (*pchar)[10] = new char[dim][10];
delete [] pchar;
Element type-id
nie może zawierać const
deklaracji klasy , volatile
lub deklaracji wyliczenia. Następujące wyrażenie jest źle sformułowane:
volatile char *vch = new volatile char[20];
Operator new
nie przydziela typów odwołań, ponieważ nie są obiektami.
Nie new
można użyć operatora do przydzielenia funkcji, ale może służyć do przydzielania wskaźników do funkcji. Poniższy przykład przydziela, a następnie zwalnia tablicę siedmiu wskaźników do funkcji, które zwracają liczby całkowite.
int (**p) () = new (int (*[7]) ());
delete p;
Jeśli używasz operatora new
bez dodatkowych argumentów i kompilujesz z opcją /GX
, /EHa
lub /EHs
, kompilator generuje kod do wywołania operatora delete
, jeśli konstruktor zgłosi wyjątek.
Na poniższej liście opisano elementy gramatyczne elementu new
:
new-placement
Zapewnia sposób przekazywania dodatkowych argumentów, jeśli przeciążysz new
element .
type-id
Określa typ, który ma zostać przydzielony; może być wbudowanym lub zdefiniowanym przez użytkownika typem. Jeśli specyfikacja typu jest skomplikowana, można ją otaczać nawiasami, aby wymusić kolejność powiązania. Typ może być symbolem zastępczym (auto
), którego typ jest określany przez kompilator.
new-initializer
Zawiera wartość zainicjowanego obiektu. Nie można określić inicjatorów dla tablic. Operator new
utworzy tablice obiektów tylko wtedy, gdy klasa ma konstruktor domyślny.
noptr-new-declarator
Określa granice tablicy. Podczas przydzielania tablicy wielowymiarowej wszystkie wymiary, z wyjątkiem pierwszego muszą być wyrażeniami stałymi, które oceniają wartości dodatnie, konwertowane na std::size_t
wartość . Najbardziej lewy wymiar tablicy może być dowolnym wyrażeniem, które daje wartość dodatnią. Wartość attribute-specifier-seq
ma zastosowanie do skojarzonego typu tablicy.
Przykład: przydzielanie i zwalnianie tablicy znaków
Poniższy przykład kodu przydziela tablicę znaków i obiekt klasy CName
, a następnie zwalnia je.
// 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;
}
Przykład: new
operator
Jeśli używasz formularza new
umieszczania operatora (formularza z większymi argumentami niż rozmiar), kompilator nie obsługuje formularza delete
umieszczania operatora, jeśli konstruktor zgłasza wyjątek. Na przykład:
// 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;
}
Inicjowanie obiektów przydzielonych za pomocą polecenia new
Opcjonalne new-initializer
pole jest uwzględniane w gramatyce operatora new
. To pole umożliwia inicjowanie nowych obiektów za pomocą konstruktorów zdefiniowanych przez użytkownika. Aby uzyskać więcej informacji na temat sposobu inicjowania, zobacz Initializers (Inicjatory). W poniższym przykładzie pokazano, jak używać wyrażenia inicjalizacji z operatorem 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 };
// ...
}
W tym przykładzie obiekt CheckingAcct
jest przydzielany przy użyciu new
operatora, ale nie określono domyślnej inicjowania. Dlatego jest wywoływany domyślny konstruktor klasy Acct()
, . Następnie obiekt SavingsAcct
jest przydzielany w taki sam sposób, z tą różnicą, że jawnie zainicjowano go do wersji 34.98. Ponieważ 34.98 jest typu double
, konstruktor, który przyjmuje argument tego typu, jest wywoływany w celu obsługi inicjowania. Na koniec typ HowMuch
nieklasowy jest inicjowany do wersji 43.0.
Jeśli obiekt jest typu klasy i klasa ma konstruktory (jak w poprzednim przykładzie), obiekt może zostać zainicjowany przez new
operatora tylko wtedy, gdy zostanie spełniony jeden z tych warunków:
Argumenty podane w inicjatorze są zgodne z argumentami konstruktora.
Klasa ma domyślny konstruktor (konstruktor, który można wywołać bez argumentów).
Jawne inicjowanie poszczególnych elementów nie można wykonać podczas przydzielania tablic przy użyciu new
operatora; wywoływany jest tylko konstruktor domyślny, jeśli istnieje. Aby uzyskać więcej informacji, zobacz Argumenty domyślne.
Jeśli alokacja pamięci zakończy się niepowodzeniem (operator new
zwraca wartość 0), nie zostanie wykonana żadna inicjalizacja. To zachowanie chroni przed próbami zainicjowania danych, które nie istnieją.
Podobnie jak w przypadku wywołań funkcji, kolejność oceniania wyrażeń zainicjowanych nie jest zdefiniowana. Ponadto nie należy polegać na tym, że wyrażenia są obliczane całkowicie przed rozpoczęciem alokacji pamięci. Jeśli alokacja pamięci zakończy się niepowodzeniem, a new
operator zwróci zero, niektóre wyrażenia w inicjatorze mogą nie być obliczane całkowicie.
Okres istnienia obiektów przydzielonych za pomocą polecenia new
Obiekty przydzielone operatorowi new
nie są niszczone, gdy zakres, w którym są zdefiniowane, jest zamykany. new
Ponieważ operator zwraca wskaźnik do przydzielanych obiektów, program musi zdefiniować wskaźnik z odpowiednim zakresem, aby uzyskać dostęp do tych obiektów i usunąć je. Na przykład:
// 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.
}
Gdy wskaźnik AnotherArray
wykracza poza zakres w tym przykładzie, nie można już usunąć obiektu.
Jak new
to działa
Wyrażenie new-expression
(zawierające new
operator) wykonuje trzy czynności:
Lokalizuje i rezerwuje pamięć dla obiektu lub obiektów, które mają zostać przydzielone. Po zakończeniu tego etapu zostanie przydzielona prawidłowa ilość miejsca do magazynowania, ale nie jest jeszcze obiektem.
Inicjalizuje obiekt(y). Po zakończeniu inicjalizacji, wystarczająca ilość informacji jest obecna dla przydzielenia pamięci, która ma być obiektem.
Zwraca wskaźnik do obiektów typu wskaźnika pochodzącego z
new-type-id
lubtype-id
. Program używa tego wskaźnika do dostępu do nowo przydzielonego obiektu.
Operator new
wywołuje funkcję operator new
. W przypadku tablic dowolnego typu i obiektów, które nie class
są typami , struct
lub union
, funkcja ::operator new
globalna , jest wywoływana w celu przydzielenia magazynu. Obiekty typu klasy mogą definiować własną operator new
statyczną funkcję składową dla poszczególnych klas.
Gdy kompilator napotka new
operator w celu przydzielenia obiektu typu T
, wystawia wywołanie metody T::operator new( sizeof(T) )
lub, jeśli nie zdefiniowano operator new
żadnego użytkownika, ::operator new( sizeof(T) )
. W ten sposób new
operator może przydzielić prawidłową ilość pamięci dla obiektu.
Uwaga
Argumentem do operator new
jest typ std::size_t
. Ten typ jest definiowany w pliku direct.h>, <malloc.h>, <memory.h>, <search.h>, <stddef.h>, <stdio.h>, <stdlib.h>, <string.h> i <time.h><.
Opcja w gramatyce umożliwia określenie new-placement
(zobacz Gramatyka dla new
operatora). Parametr new-placement
może służyć tylko do implementacji zdefiniowanych operator new
przez użytkownika ; umożliwia przekazywanie dodatkowych informacji do operator new
elementu . Wyrażenie z polem new-placement
takim jak T *TObject = new ( 0x0040 ) T;
jest tłumaczone na T *TObject = T::operator new( sizeof( T ), 0x0040 );
, jeśli klasa T ma składową operator new
, w przeciwnym razie na T *TObject = ::operator new( sizeof( T ), 0x0040 );
.
Pierwotnym zamiarem new-placement
pola było umożliwienie przydzielania obiektów zależnych od sprzętu na adresach określonych przez użytkownika.
Uwaga
Mimo że w poprzednim przykładzie pokazano tylko jeden argument w new-placement
polu, nie ma ograniczenia liczby dodatkowych argumentów, które można przekazać w operator new
ten sposób.
Nawet jeśli operator new
zdefiniowano dla typu T
klasy , można jawnie użyć operatora new
globalnego, jak w tym przykładzie:
T *TObject = ::new TObject;
Operator rozpoznawania zakresu (::
) wymusza użycie operatora globalnego new
.
Zobacz też
Wyrażenia z operatorami jednoargumentowymi
Słowa kluczowe
new
operatory i delete
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla