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

Posted

技术标签:

【中文标题】如何删除结构的动态数组(C++)?【英文标题】:How to delete a dynamic array of structs (C++)? 【发布时间】:2016-03-27 20:11:24 【问题描述】:

我正在构建一个分配动态结构数组的类,并且结构数组包含另一个结构。 问题是结构中的所有元素都是固定大小的,那么传统的释放内存的方式就足够了吗(删除[]数组)?

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

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

【问题讨论】:

states 是什么类型?为什么不直接使用std::vector 或其他为您执行此操作的东西? 我在这里看不到static "结构中的所有元素都是静态的" (1) 这段代码中没有静态成员。(2) 使用std::vector 我所说的静态是指结构中的所有元素都没有分配“新”。因此,例如,我不必删除带有“delete [] states[0]->stateName”的元素。但是,是的,数组是动态的。 "static" 在 C++ 中有一个非常具体的含义,其实不是这样的。 【参考方案1】:

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

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

    销毁数组的每个元素,并且 数组本身的破坏

由于没有为该结构定义显式析构函数,并且该结构在new[] 定义中使用,因此编译器会为该结构创建一个默认的隐式析构函数(参考:ISO C++ standard working draft,第 287 页)。这个析构函数调用结构体中所有元素的析构函数,因此允许一个一个地删除数组中的元素。

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

总体而言,该组合允许使用delete[] 删除结构数组。

【讨论】:

【参考方案2】:
    所有成员都不是静态的。 是的,这几乎是删除该数组的正确方法。

【讨论】:

【参考方案3】:

是的,每个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 语句可能更安全。

【讨论】:

以上是关于如何删除结构的动态数组(C++)?的主要内容,如果未能解决你的问题,请参考以下文章

如何释放动态结构数组的内存

delete[ ] 是不是会深度删除 C++ 中的结构?

输出没有重复元素的动态数组(缩小数组)C++

如何在C++中使用动态三维数组

如果 C++ 程序发生错误,如何删除动态分配的对象?

如何在 C++ 中删除小于 X 的数组中的整数?