簡體   English   中英

如何刪除結構的動態數組(C ++)?

[英]How to delete a dynamic array of structs (C++)?

我正在建立一個分配動態結構數組的類,該結構數組包含另一個結構。 問題是結構中的所有元素都是固定大小的,所以釋放內存的常規方式就足夠了(刪除[]數組)嗎?

struct TRANSITION
{
    int transition;
    int next_state;
};

struct state
{
    int transitionCount = 0;
    string stateName;
    string stateAction;
    TRANSITION transitions[50];
};

類的構造函數/析構函數:

FSM(int n)
{
    numberOfStates = n;
    states = new state[numberOfStates];
    currentState = 0; //First state numbered state 0
    stateCount = 0;
}
~FSM() { delete[]states; };

這是刪除此數組的正確方法嗎?

  1. 沒有成員是靜態的。
  2. 是的,這幾乎是刪除該數組的正確方法。

簡短說明:是的,考慮到上面的代碼,這是正確的方法。

詳細描述:
假設變量statesstate* ,則問題可以分為兩部分:

  1. 銷毀數組的每個元素,以及
  2. 數組本身的破壞

由於沒有為該結構定義顯式析構函數,並且該結構正在new[]定義中使用,因此編譯器將為該結構創建默認的隱式析構函數(請參見: ISO C ++標准工作草案 ,第287頁)。 該析構函數調用該結構中包含的所有元素的析構函數,因此可以逐一刪除數組中的元素。

還有一個隱式運算符delete[] ,它調用所有數組元素的各個析構函數,以確保正確的級聯。 (參考: C ++參考

總體而言,該組合允許使用delete[]結構數組。

是的,對於每個new都有一個delete 考慮到我們正在處理固定大小的數組, delete[]正是所需要的。

根據RAII原則,在構造函數中具有new並在析構函數中具有delete也很好。

另一種驗證方法是檢查程序中的內存泄漏。 例如,在Visual Studio中,以下內容不顯示內存泄漏:

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

#include <iostream>
#include <string>

#ifdef _DEBUG
#ifndef DBG_NEW
#define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
#define new DBG_NEW
#endif
#endif  // _DEBUG

struct TRANSITION {
    int transition;
    int next_state;
};

struct state {
    int transitionCount = 0;
    std::string stateName;
    std::string stateAction;
    TRANSITION transitions[50];
};

class FSM {
public:
    FSM(int n);
    ~FSM();

    int numberOfStates;
    state* states;
    int currentState;
    int stateCount;
};

FSM::FSM(int n)
{
    numberOfStates = n;
    states = new state[numberOfStates];
    currentState = 0; //First state numbered state 0
    stateCount = 0;
}

FSM::~FSM() { delete[] states; };
//FSM::~FSM() {  };

int main()
{
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    FSM fsm(3);
    return 0;
}

但是,如果刪除delete[] states; 語句然后產生:

Detected memory leaks!
Dumping objects ->
{160} normal block at 0x0000024535F03B00, 16 bytes long.
 Data: < V 5E           > D8 56 F0 35 45 02 00 00 00 00 00 00 00 00 00 00 
{159} normal block at 0x0000024535F04730, 16 bytes long.
 Data: < V 5E           > B0 56 F0 35 45 02 00 00 00 00 00 00 00 00 00 00 
{158} normal block at 0x0000024535F03A10, 16 bytes long.
 Data: < T 5E           > F0 54 F0 35 45 02 00 00 00 00 00 00 00 00 00 00 
{157} normal block at 0x0000024535F03AB0, 16 bytes long.
 Data: < T 5E           > C8 54 F0 35 45 02 00 00 00 00 00 00 00 00 00 00 
{156} normal block at 0x0000024535F03DD0, 16 bytes long.
 Data: < S 5E           > 08 53 F0 35 45 02 00 00 00 00 00 00 00 00 00 00 
{155} normal block at 0x0000024535F046E0, 16 bytes long.
 Data: < R 5E           > E0 52 F0 35 45 02 00 00 00 00 00 00 00 00 00 00 
c:\users\username\documents\visual studio 2015\projects\project60\project60\main.cpp(41) : {154} normal block at 0x0000024535F052D0, 1472 bytes long.
 Data: <                > 03 00 00 00 00 00 00 00 00 00 00 00 CD CD CD CD 
Object dump complete.

跟蹤所有newdelete語句可能很棘手,因此最好的方法通常是使用標准庫容器之一,例如原型std::vector

另一種可能更輕松的修改可能是使用諸如std::unique_ptr類的智能指針:

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

#include <iostream>
#include <string>
#include <memory>

#ifdef _DEBUG
#ifndef DBG_NEW
#define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
#define new DBG_NEW
#endif
#endif  // _DEBUG

struct TRANSITION {
    int transition;
    int next_state;
};

struct state {
    int transitionCount = 0;
    std::string stateName;
    std::string stateAction;
    TRANSITION transitions[50];
};

class FSM {
public:
    FSM(int n);
    ~FSM();

    int numberOfStates;
    //state* states;
    std::unique_ptr<state[]> states;
    int currentState;
    int stateCount;
};

FSM::FSM(int n)
{
    numberOfStates = n;
    //states = new state[numberOfStates];
    states = std::make_unique<state[]>(numberOfStates);
    currentState = 0; //First state numbered state 0
    stateCount = 0;
}

//FSM::~FSM() { delete[] states; };
FSM::~FSM() {  };

int main()
{
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    FSM fsm(3);
    return 0;
}

沒有忘記delete風險,我們也可能會感到有些安全,也看不到任何new語句。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM