C++中若類中沒有默認構造函數,如何使用對象數組


前言:

如果定義一個類,有其默認的構造函數,則使用new動態實例化一個對象數組,不是件難事,如下代碼:

 1 #include <memory>
 2 #include <iostream>
 3 
 4 using namespace std;  5 
 6 class Animal  7 {  8 public:  9 #if 1        //用於后面演示,無默認構造函數
10     Animal() : num(0) 11  { 12         cout << "Animal constructor default" << endl; 13  } 14 #endif
15     Animal(int _num) : num(_num) 16  { 17         cout << "Animal constructor param" << endl; 18  } 19 
20     ~Animal() 21  { 22         cout << "Animal destructor" << endl; 23  } 24 
25     void show() 26  { 27         cout << this->num << endl; 28  } 29 
30 private: 31     int num; 32 }; 33 
34 int main() 35 { 36     Animal *ani = new Animal[5]; 37 
38     delete[]ani; 39 
40     system("pause"); 41     return 0; 42 }

運行結果:

 

 

但是如果沒有默認構造函數,會出現怎么樣呢?

看下圖報錯提示:

 

那要如何實例化一個沒有默認構造函數的對象數組呢?

下面我將介紹兩種方法:

    1. 使用C++11新特性allocator類 

    2. 使用placement new 即operator new(第三個重載版本)void* operator new(size_t  size, void *p)函數 

 

一、allocator類

對於allocator類,請看 我的另一篇blog   http://www.cnblogs.com/SimonKly/p/7819122.html

請看一下代碼關於使用如何實現無默認構造函數,動態實例化對象數組的allocator方法 

 1 //#include "CAnimal.h"
 2 #include <memory>
 3 #include <iostream>
 4 
 5 using namespace std;
 6 
 7 class Animal
 8 {
 9 public:
10 #if 1        //即使為0,沒有默認構造也是可以,
11     Animal() : num(0)
12     {
13         cout << "Animal constructor default" << endl;
14     }
15 #endif
16     Animal(int _num) : num(_num)
17     {
18         cout << "Animal constructor param" << endl;
19     }
20 
21     ~Animal()
22     {
23         cout << "Animal destructor" << endl;
24     }
25 
26     void show()
27     {
28         cout << this->num << endl;
29     }
30 
31 private:
32     int num;
33 };
34 
35 /*
36     由於allocator將內存空間的分配和對象的構建分離
37     故使用allocator分為以下幾步:
38     1.allocator與類綁定,因為allocator是一個泛型類
39     2.allocate()申請指定大小空間
40     3.construct()構建對象,其參數為可變參數,所以可以選擇匹配的構造函數
41     4.使用,與其它指針使用無異
42     5.destroy()析構對象,此時空間還是可以使用
43     6.deallocate()回收空間
44 */
45 
46 int main()
47 {
48     allocator<Animal> alloc;        //1.
49     Animal *a = alloc.allocate(5);    //2.
50 
51     //3.
52     alloc.construct(a, 1);
53     alloc.construct(a + 1);
54     alloc.construct(a + 2, 3);
55     alloc.construct(a + 3);
56     alloc.construct(a + 4, 5);
57 
58     //4.
59     a->show();
60     (a + 1)->show();
61     (a + 2)->show();
62     (a + 3)->show();
63     (a + 4)->show();
64 
65     //5.
66     for (int i = 0; i < 5; i++)
67     {
68         alloc.destroy(a + i);
69     }
70     //對象銷毀之后還可以繼續構建,因為構建和內存的分配是分離的
71     //6.
72     alloc.deallocate(a, 5);
73 
74     cin.get();
75     return 0;
76 }
View Code

 

運行結果

通過運行結果可以看出,無論是否有默認構造,allocator會選擇出最匹配的構造函數(重載) 

 

二、placement new

函數原型:

void* operator new(size_t size, void* p) throw();

函數執行忽略size,只返回p指針,不分配內存。

 

placement new具體的用法和相關技術點,請參看我的另一篇博文的第三節

http://www.cnblogs.com/SimonKly/p/7826651.html

 

具體實現:C++中若類中沒有默認構造函數,如何使用對象數組??

 

請看下面的代碼:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 class animal
 6 {
 7 public:
 8 #if 1        //用於后面演示,無默認構造函數
 9     animal() : num(0)
10     {
11         cout << "animal constructor default" << endl;
12     }
13 #endif
14     animal(int _num) : num(_num)
15     {
16         cout << "animal constructor param" << endl;
17     }
18 
19     ~animal()
20     {
21         cout << "animal destructor" << endl;
22     }
23 
24     void show()
25     {
26         cout << this->num << endl;
27     }
28 
29     void * operator new(size_t size, void *p)
30     {
31         return p;
32     }
33 
34 private:
35     int num;
36 };
37 
38 
39 int main(int args, char ** argv)
40 {
41     // 一個動態animal數組
42     void *p = operator new(5 * sizeof(animal)); // 申請緩沖器
43     animal *a = static_cast<animal *>(p);        // 轉換類型
44     
45     // 2.對象構建
46     for (int i = 0; i < 4; i++)
47     {
48         new(a + i) animal(i);// 調用重載構造
49     }
50     new(a + 4) animal;    //    也可以調用默認構造
51 
52     // 3.使用
53     for (int i = 0; i < 5; i++)
54     {
55         (a + i)->show();
56     }
57 
58     // 4.銷毀對象
59     for (int i = 0; i < 5; i++)
60     {
61         (a + i)->~animal();
62     }
63 
64     // 5.回收空間
65     delete[]p;
66 
67     cin.get();
68     return 0;
69 }

 

運行結果:

 

 

 通過運行結果可以看出,無論是否有默認構造,placement new會向已經申請的空間重新構建對象。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM