1. 靜態(tài)類成員函數(shù)
如果將成員函數(shù)聲明為靜態(tài)的(函數(shù)聲明必須包含關(guān)鍵字static,但如果函數(shù)定義是獨(dú)立的,則其中不能包含關(guān)鍵字static),則不能通過對(duì)象調(diào)用靜態(tài)成員函數(shù),且由于靜態(tài)成員函數(shù)不能與特定的對(duì)象相關(guān)聯(lián),因此靜態(tài)成員函數(shù)只能使用靜態(tài)數(shù)據(jù)成員。
2. 在構(gòu)造函數(shù)中使用new時(shí)應(yīng)注意的事項(xiàng)
- 如果在構(gòu)造函數(shù)中使用new來初始化指針成員,則應(yīng)在析構(gòu)函數(shù)中使用delete。
- new和delete必須相互兼容,new對(duì)應(yīng)delete,new[]對(duì)應(yīng)delete[]。
- 如果有多個(gè)構(gòu)造函數(shù),則必須以相同的方式使用new,要么都帶,要么都不帶。(因?yàn)橹挥幸粋€(gè)析構(gòu)函數(shù),所有構(gòu)造函數(shù)必須與其兼容)
- 應(yīng)定義一個(gè)復(fù)制構(gòu)造函數(shù),通過深度復(fù)制將一個(gè)對(duì)象初始化為另外一個(gè)對(duì)象。(具體地說,復(fù)制構(gòu)造函數(shù)應(yīng)分配足夠的空間來存儲(chǔ)復(fù)制的數(shù)據(jù),并復(fù)制數(shù)據(jù),而不僅僅是數(shù)據(jù)的地址,同時(shí),若果有受影響的靜態(tài)成員,要及時(shí)在復(fù)制構(gòu)造函數(shù)中更新該靜態(tài)成員)
- 應(yīng)當(dāng)定義一個(gè)賦值運(yùn)算符,通過深度復(fù)制一個(gè)對(duì)象給另外一個(gè)對(duì)象。(同時(shí)需要檢查自我賦值的情況,釋放成員指針以前指向的內(nèi)存,復(fù)制數(shù)據(jù)而不僅僅是數(shù)據(jù)的地址,并返回一個(gè)指向調(diào)用對(duì)象的引用)。
3. 有關(guān)函數(shù)返回對(duì)象的說明
當(dāng)成員函數(shù)或獨(dú)立的函數(shù)返回對(duì)象時(shí),常用的方式有:
3.1 返回指向const對(duì)象的引用
使用const引用的主要原因是為了提高效率,但該方式存在一定的限制。如果函數(shù)返回(通過調(diào)用對(duì)象的方法或?qū)?duì)象作為參數(shù))傳遞給它的對(duì)象,可以通過返回引用來提高效率。
3.2 返回指向非const對(duì)象的引用
兩種常見的返回非const對(duì)象情形是,重載賦值運(yùn)算符以及重載與cout一起使用的<<運(yùn)算符。前者這樣做是為了提高效率,而后者必須這么做。
3.3 返回對(duì)象
當(dāng)被返回的對(duì)象是被調(diào)用函數(shù)中的局部變量,則應(yīng)該返回對(duì)象。
3.4 返回從const對(duì)象
返回const對(duì)象可以避免類似force1 + force2 = net
這種奇異屬性誤用可能帶來的錯(cuò)誤。
總的來說,如果方法或函數(shù)要返回局部對(duì)象,則應(yīng)該返回對(duì)象。如果方法或函數(shù)要返回一個(gè)沒有公有復(fù)制構(gòu)造函數(shù)的類(如ostream類)的對(duì)象,則必須返回一個(gè)指向這個(gè)對(duì)象的引用。如果方法或函數(shù)可以返回對(duì)象,也可以返回對(duì)象的引用,則優(yōu)先選擇引用,提高效率。
4. new與delete
定位new運(yùn)算符能夠讓使用者在分配內(nèi)存時(shí)能夠指定內(nèi)存位置。但這種運(yùn)算符在應(yīng)用于對(duì)象的時(shí)候,應(yīng)該注意:delete可以與常規(guī)的new運(yùn)算符配合使用,但不能與定位new運(yùn)算符配合使用。原因見下例:
// placenew1.cpp -- new, placement new, no delete
#include < iostream >
#include < new >
#include < string >
using namespace std;
const int BUF = 512;
class JustTesting
{
private:
string words;
int number;
public:
JustTesting(const string &s = "Just Testing", int n = 0)
{
words = s;
number = n;
cout < < words < < " constructedn";
}
~JustTesting() { cout < < words < < " destroyedn"; }
void Show() const { cout < < words < < ", " < < number < < endl; }
};
int main()
{
char *buffer = new char[BUF]; // get a block of memory
JustTesting *pc1, *pc2;
pc1 = new (buffer) JustTesting; // place object in buffer
pc2 = new JustTesting("Heap1", 20); // place object on heap
cout < < "Memory block addresses:n"
< < "buffer: "
< < (void *)buffer < < " heap: " < < pc2 < < endl;
cout < < "Memory contents:n";
cout < < pc1 < < ": ";
pc1- >Show();
cout < < pc2 < < ": ";
pc2- >Show();
JustTesting *pc3, *pc4;
pc3 = new (buffer) JustTesting("Bad Idea", 6);
pc4 = new JustTesting("Heap2", 10);
cout < < "Memory contents:n";
cout < < pc3 < < ": ";
pc3- >Show();
cout < < pc4 < < ": ";
pc4- >Show();
delete pc2; // free Heap1
delete pc4; // free Heap2
delete[] buffer; // free buffer
cout < < "Donen";
return 0;
}
其中,使用new運(yùn)算符創(chuàng)建了一個(gè)512字節(jié)的內(nèi)存緩存區(qū),然后在使用new運(yùn)算符在堆中創(chuàng)建兩個(gè)JustTesting
對(duì)象。并試圖使用定位new運(yùn)算符在內(nèi)存緩沖區(qū)創(chuàng)建兩個(gè)JustTesting
對(duì)象,最后在使用delete來釋放new分配的內(nèi)存時(shí)出現(xiàn)異常,上述代碼的輸出如下:
Just Testing constructed
Heap1 constructed
Memory block addresses:
buffer: 00320AB0 heap: 00320CE0
Memory contents:
00320AB0: Just Testing, 0
00320CE0: Heap1, 20
Bad Idea constructed
Heap2 constructed
Memory contents:
00320AB0: Bad Idea, 6
00320EC8: Heap2, 10
Heap1 destroyed
Heap2 destroyed
Done
根據(jù)打印信息,很明顯發(fā)現(xiàn)pc1
和pc3
的析構(gòu)函數(shù)未被正常調(diào)用,且pc3
在創(chuàng)建的時(shí)候,直接覆蓋了pc1
的內(nèi)存。
在使用定位new運(yùn)算符時(shí),要注意一下兩點(diǎn):
- 要保證每個(gè)對(duì)象要使用不同的內(nèi)存單元(即需要提供兩個(gè)不同的內(nèi)存地址,并確保兩個(gè)內(nèi)存單元不存在重疊)。
- 如果使用定位new運(yùn)算符來為對(duì)象分配內(nèi)存,必須保證其析構(gòu)函數(shù)能夠正常的被調(diào)用(delete可以和常規(guī)的new運(yùn)算符配合使用,但不能與定位new運(yùn)算符配合使用,因此,delete對(duì)于定位new運(yùn)算符對(duì)其分配內(nèi)存做了什么一無所知)。
修改后的代碼:
// placenew2.cpp -- new, placement new, no delete
#include < iostream >
#include < new >
#include < string >
using namespace std;
const int BUF = 512;
class JustTesting
{
private:
string words;
int number;
public:
JustTesting(const string &s = "Just Testing", int n = 0)
{
words = s;
number = n;
cout < < words < < " constructedn";
}
~JustTesting() { cout < < words < < " destroyedn"; }
void Show() const { cout < < words < < ", " < < number < < endl; }
};
int main()
{
char *buffer = new char[BUF]; // get a block of memory
JustTesting *pc1, *pc2;
pc1 = new (buffer) JustTesting; // place object in buffer
pc2 = new JustTesting("Heap1", 20); // place object on heap
cout < < "Memory block addresses:n"
< < "buffer: "
< < (void *)buffer < < " heap: " < < pc2 < < endl;
cout < < "Memory contents:n";
cout < < pc1 < < ": ";
pc1- >Show();
cout < < pc2 < < ": ";
pc2- >Show();
JustTesting *pc3, *pc4;
// fix placement new location
pc3 = new (buffer + sizeof(JustTesting))
JustTesting("Better Idea", 6);
pc4 = new JustTesting("Heap2", 10);
cout < < "Memory contents:n";
cout < < pc3 < < ": ";
pc3- >Show();
cout < < pc4 < < ": ";
pc4- >Show();
delete pc2; // free Heap1
delete pc4; // free Heap2
// 顯式銷毀放置的新對(duì)象
pc3- >~JustTesting(); // destroy object pointed to by pc3
pc1- >~JustTesting(); // destroy object pointed to by pc1
delete[] buffer; // free buffer
cout < < "Donen";
return 0;
}
其對(duì)應(yīng)的輸出:
Just Testing constructed
Heap1 constructed
Memory block addresses:
buffer: 00320AB0 heap: 00320CE0
Memory contents:
00320AB0: Just Testing, 0
00320CE0: Heap1, 20
Better Idea constructed
Heap2 constructed
Memory contents:
00320AD0: Better Idea, 6
00320EC8: Heap2, 10
Heap1 destroyed
Heap2 destroyed
Better Idea destroyed
Just Testing destroyed
Done
對(duì)于使用定位new運(yùn)算符創(chuàng)建的對(duì)象,由于晚創(chuàng)建的對(duì)象可能依賴于早創(chuàng)建的對(duì)象,所以在刪除時(shí)應(yīng)以與創(chuàng)建順序相反的順序進(jìn)行刪除。
-
存儲(chǔ)器
+關(guān)注
關(guān)注
38文章
7527瀏覽量
164168 -
按位運(yùn)算符
+關(guān)注
關(guān)注
0文章
3瀏覽量
4794
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論