我正在构建一个分配动态结构数组的类,结构数组包含另一个结构。 问题是结构中的所有元素都是固定大小的,那么释放内存的常规方法是否足够(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; };
这是删除此数组的正确方法吗?
答案 0 :(得分:1)
答案 1 :(得分:1)
简短描述:是的,考虑到上面的代码,这是正确的方法。
详细说明:
假设变量public
是states
,问题可以分为两部分:
由于没有为结构定义显式析构函数,并且结构正在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.
跟踪所有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
语句。