程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++中類成員使用前需要初始化的重要性,初始化重要性

C++中類成員使用前需要初始化的重要性,初始化重要性

編輯:C++入門知識

C++中類成員使用前需要初始化的重要性,初始化重要性


今天寫程序的時候,創建了一個結構體:

struct BufferObj {
char* buf;
int bufLen;
SOCKADDR_STORAGE addr;
int addrLen;
struct BufferObj* next;
};

該結構體有一個next指針,本意是這個指針初始的時候應該為NULL,如果有新的BufferObj添加,這個next指針就會指向這個新添加的BufferObj,其實就是一個鏈表。

程序中有一個生產者線程使用enqueueBufferObj方法向鏈表裡面添加BufferObj:

void enqueueBufferObj(ConnectionObj* connObj, BufferObj* bufferObj) {
    EnterCriticalSection(&connObj->sendRecvQueueCriticalSection);

    

    if (connObj->pendingSendHead == NULL) {
        connObj->pendingSendHead = connObj->pendingSendTail = bufferObj;
    } else {
        
        connObj->pendingSendTail->next = bufferObj;
        connObj->pendingSendTail = bufferObj;
    }

    LeaveCriticalSection(&connObj->sendRecvQueueCriticalSection);
}

還有一個消費者線程從這個鏈表裡面取BufferObj:

BufferObj* dequeueBufferObj(ConnectionObj* connObj) {
    BufferObj* res = NULL;

    EnterCriticalSection(&connObj->sendRecvQueueCriticalSection);

    if (connObj->pendingSendTail != NULL) {
        res = connObj->pendingSendHead;
        connObj->pendingSendHead = connObj->pendingSendHead->next;
        if (connObj->pendingSendTail == res) {
            connObj->pendingSendTail = NULL;
        }
    }
    LeaveCriticalSection(&connObj->sendRecvQueueCriticalSection);
    return res;
}

 其中,ConnectionObj結構體如下:

struct ConnectionObj {
    SOCKET s;
    HANDLE hRecvSemaphore;
    struct BufferObj* pendingSendHead;
    struct BufferObj* pendingSendTail;
    CRITICAL_SECTION sendRecvQueueCriticalSection;
};

剛開始的時候,由於程序中沒有顯示的將BufferObj的next屬性初始化NULL,導致程序運行到enqueueBufferObj方法時總是出現指針違法訪問:

connObj->pendingSendTail->next = bufferObj;

上面就是出錯的地方。程序中對於ConnectionObj中的pendingSendHead和pendingSendTail都已經顯示初始化為NULL了。經過查找發現,是因為程序中沒有顯式對

BufferObj中next進行NULL初始化,從而當消費者線程從隊列中BufferObj之後,會重新對隊列頭進行初始化,該代碼在dequeueBufferObj中:

connObj->pendingSendHead = connObj->pendingSendHead->next;

此時,如果BufferObj中的next顯示初始化為了NULL,那麼connObj->pendingSendHead的值應該為NULL,但是程序中沒有對next進行顯式初始化,所以,此時,

connObj->pendingSendHead的值為一個隨機值,這導致生產者線程使用enqueueBufferObj在向隊列中添加新BufferObj時出錯:

if (connObj->pendingSendHead == NULL) {//如果next顯式初始化了,這個條件檢測應該成立
        connObj->pendingSendHead = connObj->pendingSendTail = bufferObj;
    } else {//但是由於next沒有顯示初始化,導致pendingSendHead的值不是NULL,而是一個隨機的,因此程序錯誤的運行到這裡,出現上述錯誤
        
        connObj->pendingSendTail->next = bufferObj;
        connObj->pendingSendTail = bufferObj;
    }

 

在簡單的程序中,這中錯誤查找起來可能不是問題,但是如果程序很復雜,查找這種錯誤就會很浪費時間。因此,為了安全起見,以後對於C++中的結構體,類成員,在使用前,還是先進行初始化後為好。

 


C語言結構體的成員互相賦值?如成員使用前需要初始化?怎初始化?

1.
output函數中的for循環後面的分號去掉就行了
for(i=0; i<b; ++i);改成for(i=0; i<b; ++i)
2.結構體的初始化可以用memset,頭文件string.h
memset(jsq,0,a * sizeof( struct counter));
 

類裡面的構造函數作用?(初始化成員數據值?)

如果數據是private或protected,不能直接初始化,只能再寫單獨的函數來賦值。
你接著往後看吧,構造函數又好幾種的

很多用處的,舉幾個例子
1.處理const數據成員時,單獨寫函數是行不通的,只能用構造函數來初始化
2.構造函數的初始化列表是早於普通函數的
3.new表達式分配內存的同時還調用構造函數初始化,而普通函數做不到的
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved