如何删除动态结构数组(C ++)?

时间:2016-03-27 20:11:24

标签: c++ arrays dynamic struct

我正在构建一个分配动态结构数组的类,结构数组包含另一个结构。 问题是结构中的所有元素都是固定大小的,那么释放内存的常规方法是否足够(delete [] array)?

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; };

这是删除此数组的正确方法吗?

3 个答案:

答案 0 :(得分:1)

  1. 没有成员是静态的。
  2. 是的,这几乎是删除该阵列的正确方法。

答案 1 :(得分:1)

简短描述:是的,考虑到上面的代码,这是正确的方法。

详细说明:
假设变量publicstates,问题可以分为两部分:

  1. 销毁阵列的每个元素,
  2. 破坏阵列本身
  3. 由于没有为结构定义显式析构函数,并且结构正在state*定义中使用,因此编译器会创建一个默认的隐式析构函数(参考:ISO C++ standard working draft,第287页)对于结构。这个析构函数调用结构中包含的所有元素的析构函数,因此允许逐个删除数组的元素。

    还有一个隐式运算符new[],它调用所有数组元素的各个析构函数,以确保正确的级联。 (参考文献:C++ Reference

    总的来说,该组合允许使用delete[]删除结构数组。

答案 2 :(得分:0)

是的,对于每个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语句。