嘗試配置和初始化指定或佔位元類型之物件的物件或數位,並傳回物件適當型別的非零指標(或陣列的初始物件)。
語法
new-expression:
::
選擇newnew-placement選擇new-type-idnew-initializer選擇
::
選擇newnew-placement選擇(type-id)new-initializer選擇
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 則傳回零或擲回例外狀況。 如需詳細資訊,請參閱 new 和 delete 運算符。 您可以撰寫自定義例外狀況處理例程,並以您的函式名稱作為其自變數呼叫 _set_new_handler 運行時間連結庫函式,以變更此默認行為。
如需如何在 C++/CLI 和 C++/CX 中於 Managed 堆積上建立物件的資訊,請參閱 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而不使用任何額外的自變數,並使用、 /EHa或 /EHs 選項進行編譯/GX,則編譯程式會在建構函式擲回例外狀況時產生呼叫運算符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。 如果類別 T 具有new-placement成員operator new,則具有 之類的T *TObject = new ( 0x0040 ) T;欄位的運算式會轉譯為 T *TObject = T::operator new( sizeof( T ), 0x0040 ); ,否則為 T *TObject = ::operator new( sizeof( T ), 0x0040 );。
欄位的 new-placement 最初意圖是允許在使用者指定的位址配置硬體相依物件。
備註
雖然上述範例在 new-placement 欄位中只顯示一個自變數,但不會限制可透過這種方式傳遞 operator new 多少個額外自變數。
operator new即使已針對類別類型T定義 ,您也可以明確地使用全域運算符new,如下列範例所示:
T *TObject = ::new TObject;
範圍解析運算子 (::) 會強制使用全域 new 運算子。