简体   繁体   English

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

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

I am building a class that that allocates a dynamic array of structs and the array of structs contains another struct. 我正在建立一个分配动态结构数组的类,该结构数组包含另一个结构。 The thing is all the elements in the struct are of fixed size so would the conventional way of releasing the memory suffice (delete [ ] array)? 问题是结构中的所有元素都是固定大小的,所以释放内存的常规方式就足够了(删除[]数组)吗?

struct TRANSITION
{
    int transition;
    int next_state;
};

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

class constructor/destructor: 类的构造函数/析构函数:

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

Is this the correct way to delete this array? 这是删除此数组的正确方法吗?

  1. None of the members are static. 没有成员是静态的。
  2. Yea it's pretty much the correct way to delete that array. 是的,这几乎是删除该数组的正确方法。

Short description: Yes, considering the code above, it is the correct way. 简短说明:是的,考虑到上面的代码,这是正确的方法。

Long description: 详细描述:
Assuming that the variable states is a state* , the problem can be broken into two parts: 假设变量statesstate* ,则问题可以分为两部分:

  1. Destruction of each of the elements of the array, and 销毁数组的每个元素,以及
  2. Destruction of the array itself 数组本身的破坏

Since there is no explicit destructor defined for the struct, and the struct is being used in a new[] definition, a default implicit destructor is created by the compiler (Ref: ISO C++ standard working draft , page 287) for the struct. 由于没有为该结构定义显式析构函数,并且该结构正在new[]定义中使用,因此编译器将为该结构创建默认的隐式析构函数(请参见: ISO C ++标准工作草案 ,第287页)。 This destructor calls destructors of all the elements included in the struct and hence allows deletion of elements of the array one by one. 该析构函数调用该结构中包含的所有元素的析构函数,因此可以逐一删除数组中的元素。

There is also an implicit operator delete[] that calls the individual destructors of all the array elements ensuring a proper cascade. 还有一个隐式运算符delete[] ,它调用所有数组元素的各个析构函数,以确保正确的级联。 (Ref: C++ Reference ) (参考: C ++参考

Overall, the combination allows deleting the array of structs using delete[] . 总体而言,该组合允许使用delete[]结构数组。

Yes, for each new there is a delete . 是的,对于每个new都有一个delete And given that we're dealing with a fixed size array the delete[] is exactly what is required. 考虑到我们正在处理固定大小的数组, delete[]正是所需要的。

Also good to have the new in the constructor and the delete in the destructor as per RAII principles. 根据RAII原则,在构造函数中具有new并在析构函数中具有delete也很好。

Another way to verify could be to check for memory leaks in the program. 另一种验证方法是检查程序中的内存泄漏。 In Visual Studio for example the following shows no memory leaks: 例如,在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;
}

But if you remove the delete[] states; 但是,如果删除delete[] states; statement then it produces: 语句然后产生:

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.

It can be tricky to keep track of all the new and delete statements, so the best approach would normally be to use one of the standard library containers such as the prototypical std::vector . 跟踪所有newdelete语句可能很棘手,因此最好的方法通常是使用标准库容器之一,例如原型std::vector

Another, perhaps lighter, modification could be to use smart pointers such as std::unique_ptr : 另一种可能更轻松的修改可能是使用诸如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;
}

No risk of forgetting a delete and we can feel perhaps a bit safer not seeing any new statements either. 没有忘记delete风险,我们也可能会感到有些安全,也看不到任何new语句。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM