C++ C++;--对于本例,如何编写正确的代码来释放分配的内存?

C++ C++;--对于本例,如何编写正确的代码来释放分配的内存?,c++,C++,基于此,, 我认为发布的代码存在内存泄漏b/c数组中存储的分配内存从未释放。我做了如下修改: #include "stdafx.h" #include <iostream> using namespace std; class Giant { public: Giant() { m_id = s_next++; } void fee() { cout << m_id << "-fee

基于此,, 我认为发布的代码存在内存泄漏b/c数组中存储的分配内存从未释放。我做了如下修改:

#include "stdafx.h"
#include <iostream>
using namespace std;

class Giant
{
public:
    Giant()
    {
        m_id = s_next++;
    }
    void fee()
    {
        cout << m_id << "-fee  ";
    }
    void phi()
    {
        cout << m_id << "-phi  ";
    }
    void pheaux()
    {
        cout << m_id << "-pheaux  ";
    }
private:
    int m_id;
    static int s_next;
};
int Giant::s_next = 0;

// Define a Command interface with a method signature like execute().
class Command
{
public:
    typedef void(Giant:: *Action)();
    Command(Giant *object, Action method)
    {
        m_object = object;
        m_method = method;
    }
    void execute()
    {
        (m_object->*m_method)();
    }
private:
    Giant *m_object;
    Action m_method;
};

template <typename T> class Queue
{
public:
    Queue()
    {
        m_add = m_remove = 0;
    }
    void enque(T *c)
    {
        m_array[m_add] = c;
        m_add = (m_add + 1) % SIZE;
    }
    T *deque()
    {
        int temp = m_remove;
        m_remove = (m_remove + 1) % SIZE;
        return m_array[temp];
    }
private:
    enum
    {
        SIZE = 8
    };
    T *m_array[SIZE];
    int m_add, m_remove;
};

int main()
{
    Queue<Command> que;
    Command *input[] = 
    {
        new Command(new Giant, &Giant::fee), 
        new Command(new Giant, &Giant::phi),
        new Command(new Giant, &Giant::pheaux), 
        new Command(new Giant, &Giant::fee), 
        new Command(new Giant, &Giant::phi), 
        new Command(new Giant, &Giant::pheaux)
    };

    // 24 / 4 = 6
    size_t arrSize = sizeof(input)/sizeof(input[0]);

    for (int i = 0; i < 6; i++)
        que.enque(input[i]);

    for (int i = 0; i < 6; i++)
        que.deque()->execute();
    cout << '\n';

    // I add the following code to release the memory, however I am not sure
    // whether o not this is enough
    // There are two memory allocations in this code
    // 1-> new command and 2->new Giant
    // I think my code only release the memory allocated by new command.
    // Is this correct?
    for (int i = 0; i < 6; i++)
    {
        delete input[i];
        input[i] = NULL;
    }
}
#包括“stdafx.h”
#包括
使用名称空间std;
阶级巨人
{
公众:
巨人()
{
m_id=s_next++;
}
无效费用()
{

cout您是正确的-
删除输入[i]
只会删除
命令的实例
,而不会删除
巨人的实例

您是正确的-
删除输入[i]
将只删除
命令的实例,而不是
巨人的实例。您是正确的。存在泄漏。

您是正确的。存在泄漏


我认为我的代码只释放新命令分配的内存。这是正确的吗

是的,这是正确的。但是

你为什么还要在堆上分配它们呢?只要在堆栈上创建它们,并在需要的地方传递指针,那么你就不会忘记释放它们

Giant giant;
std::vector<Command> input;
input.push_back(Command(&giant, &Giant::fee));
input.push_back(Command(&giant, &Giant::phi));
input.push_back(Command(&giant, &Giant::pheaux));
input.push_back(Command(&giant, &Giant::fee));
input.push_back(Command(&giant, &Giant::phi));
input.push_back(Command(&giant, &Giant::pheaux));

// ...

for (int i = 0; i < input.size(); i++)
    que.enque(&input[i]);
巨人;
向量输入;
input.push_back(命令(&giant,&giant::fee));
input.push_back(命令(&giant,&giant::phi));
input.push_back(命令(&giant,&giant::pheaux));
input.push_back(命令(&giant,&giant::fee));
input.push_back(命令(&giant,&giant::phi));
input.push_back(命令(&giant,&giant::pheaux));
// ...
对于(int i=0;i

你应该查找RAII习惯用法。C++中的一个坏习惯是在构造函数之外的任何地方放置<代码>新<代码>(除非直接传递给智能指针)。,将

delete
放在析构函数之外的任何位置都是不好的做法。尝试一次分配多个对象,而不将每个对象分别包装在RAII或智能指针中也是不好的

您可以编写不使用RAII/smart指针的代码,但要保证在任何情况下都不会出现内存泄漏,尤其是在代码中任何地方抛出异常时,这将是非常困难的

另外,您可以使用现有的队列数据结构,而不是滚动自己的队列数据结构。我强烈建议您避免滚动自己的数据结构,除非您真的必须这样做,或者您特别尝试了解数据结构在内部如何工作(并且您没有将该代码投入生产).这段代码似乎是成员函数指针的演示,因此我认为队列实现的复杂性是偶然的

改用
std::queue


我认为我的代码只释放新命令分配的内存。这是正确的吗

是的,这是正确的。但是

你为什么还要在堆上分配它们呢?只要在堆栈上创建它们,并在需要的地方传递指针,那么你就不会忘记释放它们

Giant giant;
std::vector<Command> input;
input.push_back(Command(&giant, &Giant::fee));
input.push_back(Command(&giant, &Giant::phi));
input.push_back(Command(&giant, &Giant::pheaux));
input.push_back(Command(&giant, &Giant::fee));
input.push_back(Command(&giant, &Giant::phi));
input.push_back(Command(&giant, &Giant::pheaux));

// ...

for (int i = 0; i < input.size(); i++)
    que.enque(&input[i]);
巨人;
向量输入;
input.push_back(命令(&giant,&giant::fee));
input.push_back(命令(&giant,&giant::phi));
input.push_back(命令(&giant,&giant::pheaux));
input.push_back(命令(&giant,&giant::fee));
input.push_back(命令(&giant,&giant::phi));
input.push_back(命令(&giant,&giant::pheaux));
// ...
对于(int i=0;i

你应该查找RAII习惯用法。C++中的一个坏习惯是在构造函数之外的任何地方放置<代码>新<代码>(除非直接传递给智能指针)。,将

delete
放在析构函数之外的任何位置都是不好的做法。尝试一次分配多个对象,而不将每个对象分别包装在RAII或智能指针中也是不好的

您可以编写不使用RAII/smart指针的代码,但要保证在任何情况下都不会出现内存泄漏,尤其是在代码中任何地方抛出异常时,这将是非常困难的

另外,您可以使用现有的队列数据结构,而不是滚动自己的队列数据结构。我强烈建议您避免滚动自己的数据结构,除非您真的必须这样做,或者您特别尝试了解数据结构在内部如何工作(并且您没有将该代码投入生产).这段代码似乎是成员函数指针的演示,因此我认为队列实现的复杂性是偶然的

改为使用
std::queue

“我认为我的代码只释放新命令分配的内存。这是否正确?”

是的,如果你的意思是我认为你的意思的话。
命令
实例被解除分配。但是每个
命令
实例都有一个指向动态分配的
巨人
的指针,这个巨人没有解除分配

解决这个特殊程序的一个简单方法是不使用动态分配

更一般地说,根据需要使用容器类,如
std::queue
和智能指针,如
std::auto_ptr

干杯&hth.,

“我想我的代码只会释放新命令分配的内存。这是正确的吗?”

是的,如果你的意思是我认为你的意思的话。
命令
实例被解除分配。但是每个
命令
实例都有一个指向动态分配的
巨人
的指针,这个巨人没有解除分配

解决这个特殊程序的一个简单方法是不使用动态分配

更一般地说,根据需要使用容器类,如
std::queue
和智能指针,如
std::auto_ptr


干杯,

您需要使用智能指针来表示所有权:

就个人而言,我将使用队列对象作为所有者。
但还有其他选择(您的解决方案可能非常依赖于您尚未阐明的上下文)

例如,对象
input
可以拥有所有权,但您需要将其从一个简单的数组转换为您自己的数组
void enque(std::auto_ptr<T> c) // This explicitly tells the caller that you are
                               // taking ownership and they should not try and manage
                               // object after you receive it.
    Queue<Command> que;
    Giant giant;
    Command input[] = 
    {
        Command(&giant, &Giant::fee), 
        Command(&giant, &Giant::phi),
        Command(&giant, &Giant::pheaux), 
        Command(&giant, &Giant::fee), 
        Command(&giant, &Giant::phi), 
        Command(&giant, &Giant::pheaux)
    };

    // 24 / 4 = 6
    size_t arrSize = sizeof(input)/sizeof(input[0]);

    for (int i = 0; i < arrSize; i++)
        que.enque(input+i);