new
– operátor (C++)
Pokusí se přidělit a inicializovat objekt nebo pole objektů zadaného nebo zástupného typu a vrátí vhodný typ nenulového ukazatele na objekt (nebo na počáteční objekt pole).
Syntaxe
new-expression
:
::
optnew-placement
optnew-initializer
new-type-id
new
::
optopt)
new-initializer
type-id
(
new
new-placement
new-placement
:
(
expression-list
)
new-type-id
:
type-specifier-seq
new-declarator
Rozhodnout
new-declarator
:
ptr-operator
new-declarator
Rozhodnout
noptr-new-declarator
noptr-new-declarator
:
[
expression
]
attribute-specifier-seq
Rozhodnout
noptr-new-declarator
[
constant-expression
]
attribute-specifier-seq
Rozhodnout
new-initializer
:
(
expression-list
Rozhodnout)
braced-init-list
Poznámky
Pokud se nezdaří, new
vrátí nulu nebo vyvolá výjimku. Další informace naleznete v tématu Operátory a delete
operátorynew
. Toto výchozí chování můžete změnit tak, že jako argument napíšete vlastní rutinu zpracování výjimek a zavoláte _set_new_handler
funkci knihovny runtime s názvem vaší funkce.
Informace o tom, jak vytvořit objekt ve spravované haldě v C++/CLI a C++/CX, najdete v tématu gcnew.
Poznámka
Rozšíření komponent Microsoft C++ (C++/CX) poskytuje podporu klíčového new
slova pro přidání položek slotu vtable. Další informace najdete v tématu new
(nový slot v tabulce vtable)
Pokud new
se používá k přidělení paměti pro objekt třídy C++, je volána konstruktor objektu po přidělení paměti.
Pomocí operátoru delete
uvolněte paměť přidělenou operátorem new
. Pomocí operátoru delete[]
odstraňte pole přidělené operátorem new
.
Následující příklad přidělí a potom uvolní dvojrozměrnou matici znaků o velikosti dim
10. Při přidělování multidimenzionálního pole musí být všechny dimenze s výjimkou první konstantní výrazy, které se vyhodnotí jako kladné hodnoty. Maticová dimenze úplně vlevo může být libovolný výraz, který se vyhodnotí jako kladná hodnota. Při přidělování pole pomocí operátoru new
může být první dimenze nula; new
operátor vrátí jedinečný ukazatel.
char (*pchar)[10] = new char[dim][10];
delete [] pchar;
Nemůže type-id
obsahovat const
, , , volatile
deklarace tříd nebo výčtové deklarace. Následující výraz je neformulovaný:
volatile char *vch = new volatile char[20];
Operátor new
nepřiděluje referenční typy, protože nejsou objekty.
Operátor new
se nedá použít k přidělení funkce, ale dá se použít k přidělení ukazatelů na funkce. Následující příklad přidělí a potom uvolní pole sedmi ukazatelů na funkce, které vracejí celá čísla.
int (**p) () = new (int (*[7]) ());
delete p;
Pokud použijete operátor new
bez dalších argumentů a zkompilujete s parametrem /GX
, /EHa
nebo /EHs
možnost, kompilátor vygeneruje kód pro volání operátor delete
, pokud konstruktor vyvolá výjimku.
Následující seznam popisuje gramatické prvky new
:
new-placement
Poskytuje způsob předávání nadbytečných argumentů při přetížení new
.
type-id
Určuje typ, který má být přidělen; může to být předdefinovaný nebo uživatelem definovaný typ. Pokud je specifikace typu složitá, může být ohraničena závorky a vynutit pořadí vazby. Typ může být zástupný symbol (auto
), jehož typ je určen kompilátorem.
new-initializer
Poskytuje hodnotu pro inicializovaný objekt. Inicializátory nelze zadat pro pole. Operátor new
vytvoří pole objektů pouze v případě, že třída má výchozí konstruktor.
noptr-new-declarator
Určuje hranice pole. Při přidělování multidimenzionálního pole musí být všechny dimenze s výjimkou první konstantní výrazy, které se vyhodnocují jako kladné hodnoty konvertibilní na std::size_t
. Maticová dimenze úplně vlevo může být libovolný výraz, který se vyhodnotí jako kladná hodnota. Platí attribute-specifier-seq
pro přidružený typ pole.
Příklad: Přidělení a uvolnění pole znaků
Následující příklad kódu přidělí pole znaků a objekt třídy CName
a pak je uvolní.
// 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;
}
Příklad: new
operátor
Pokud použijete formu umístění operátoru new
(formulář s více argumenty než velikost), kompilátor nepodporuje formulář delete
umístění operátoru, pokud konstruktor vyvolá výjimku. Příklad:
// 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;
}
Inicializace objektů přidělených pomocí new
new-initializer
Volitelné pole je součástí gramatiky operátorunew
. Toto pole umožňuje inicializaci nových objektů pomocí uživatelem definovaných konstruktorů. Další informace o tom, jak se inicializace provádí, najdete v tématu Inicializátory. Následující příklad ukazuje, jak použít inicializační výraz s operátorem 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 };
// ...
}
V tomto příkladu je objekt CheckingAcct
přidělen pomocí operátoru new
, ale není zadána žádná výchozí inicializace. Proto je volána výchozí konstruktor pro třídu. Acct()
Pak je objekt SavingsAcct
přidělen stejným způsobem, s tím rozdílem, že je explicitně inicializován na 34,98. Protože 34.98 je typu double
, konstruktor, který přebírá argument tohoto typu je volána pro zpracování inicializace. Nakonec se typ HowMuch
, který není třída, inicializuje na 43.0.
Pokud je objekt typu třídy a tato třída má konstruktory (jako v předchozím příkladu), lze objekt inicializovat operátorem new
pouze v případě, že je splněna jedna z těchto podmínek:
Argumenty zadané v inicializátoru odpovídají argumenty konstruktoru.
Třída má výchozí konstruktor (konstruktor, který lze volat bez argumentů).
Explicitní inicializace jednotlivých prvků nelze provést při přidělování polí pomocí operátoru new
; volá se pouze výchozí konstruktor, pokud je k dispozici. Další informace naleznete v tématu Výchozí argumenty.
Pokud přidělení paměti selže (operator new
vrátí hodnotu 0), neprojde žádná inicializace. Toto chování chrání před pokusy o inicializaci dat, která neexistují.
Stejně jako u volání funkcí není definováno pořadí, ve kterém se inicializované výrazy vyhodnocují. Kromě toho byste se neměli spoléhat na to, že se tyto výrazy vyhodnocují úplně před přidělením paměti. Pokud přidělení paměti selže a operátor vrátí nulu new
, některé výrazy v inicializátoru nemusí být vyhodnoceny úplně.
Doba života objektů přidělených pomocí new
Objekty přidělené operátorem new
se při ukončení oboru, ve kterém jsou definovány, nezničí. Vzhledem k tomu, že new
operátor vrátí ukazatel na objekty, které přiděluje, musí program definovat ukazatel s vhodným oborem pro přístup k těmto objektům a odstranit je. Příklad:
// 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.
}
Jakmile ukazatel AnotherArray
v příkladu překročí obor, nelze již objekt odstranit.
Jak new
funguje
Výraz new-expression
obsahující new
operátor dělá tři věci:
Vyhledává a vyhrazuje úložiště pro objekt nebo objekty, které mají být přiděleny. Po dokončení této fáze se přidělí správné množství úložiště, ale zatím se nejedná o objekt.
Inicializuje objekt(y). Po dokončení inicializace je k dispozici dostatek informací pro přidělené úložiště, aby byl vytvořen objekt.
Vrátí ukazatel na objekty typu ukazatele odvozeného od
new-type-id
nebotype-id
. Program používá tento ukazatel pro přístup k nově přidělenému objektu.
Operátor new
vyvolá funkci operator new
. Pro pole libovolného typu a pro objekty, které nejsou class
, struct
nebo union
typy, globální funkce, ::operator new
je volána k přidělení úložiště. Objekty typu třídy mohou definovat vlastní operator new
statickou členovou funkci na základě jednotlivých tříd.
Když kompilátor narazí na new
operátor přidělení objektu typu T
, vydá volání T::operator new( sizeof(T) )
nebo, pokud není definován žádný uživatelem definovaný operator new
, ::operator new( sizeof(T) )
. Je to způsob, jakým new
může operátor přidělit správné množství paměti objektu.
Poznámka
operator new
Argument typu std::size_t
. Tento typ je definován v <direct.h>, <malloc.h>, <memory.h>, <search.h>, <stddef.h>, <stdio.h>, <stdlib.h>, <string.h> a <time.h>.
Možnost v gramatikě umožňuje specifikaci new-placement
(viz Gramatika pro new
operátor). Parametr new-placement
lze použít pouze pro uživatelem definované implementace operator new
; umožňuje předání dodatečných informací operator new
. Výraz s polem new-placement
, jako T *TObject = new ( 0x0040 ) T;
je například přeložen do T *TObject = T::operator new( sizeof( T ), 0x0040 );
třídy T má člen operator new
, jinak na T *TObject = ::operator new( sizeof( T ), 0x0040 );
.
Původním záměrem new-placement
pole bylo umožnit přidělení hardwarových objektů závislých na uživatelích.
Poznámka
I když předchozí příklad ukazuje pouze jeden argument v new-placement
poli, neexistuje žádné omezení, kolik dalších argumentů lze tímto operator new
způsobem předat.
I když operator new
byl definován pro typ T
třídy , můžete použít globální operátor new
explicitně, jako v tomto příkladu:
T *TObject = ::new TObject;
Operátor rozlišení oboru (::
) vynutí použití globálního new
operátoru.
Viz také
Výrazy s unárními operátory
Klíčová slova
new
a delete
operátory
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro