如何删除结构的动态数组(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】:
简短描述:是的,考虑到上面的代码,这是正确的方法。
详细说明:
假设变量states
是state*
,问题可以分为两部分:
-
销毁数组的每个元素,并且
数组本身的破坏
由于没有为该结构定义显式析构函数,并且该结构在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.
跟踪所有new
和delete
语句可能很棘手,因此最好的方法通常是使用标准库容器之一,例如原型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++)?的主要内容,如果未能解决你的问题,请参考以下文章