C ++内存 - 用'new'创建的原始类型变量是否需要删除?

时间:2012-10-26 10:26:26

标签: c++ winapi memory memory-management allocation

在C ++中进行内存管理时,我有点新鲜。我读到如果你创建一个带有new关键字的类,你必须delete该对象释放它的内存。我还读到在堆栈上创建原始类型,例如intcharbool,这意味着它们在超出范围时会被删除。

但是使用new关键字创建的原始类型呢?我是否需要明确呼叫delete?这些是在类上创建的吗?或者因为它们是原始的,它们仍然在堆栈中创建?

我在问,因为我正在使用new关键字分配LPTSTR,但我担心如果我不调用delete,则永远不会释放内存。这是我的代码,注释中有一个简单的问题:

#include <Windows.h>
#include <tchar.h>
#include <string>

#ifdef _UNICODE
    typedef std::wstring Str;
#else // ANSI
    typedef std::string Str;
#endif

Str GetWndStr(HWND hwnd) {
    const int length = GetWindowTextLength(hwnd);

    if (length != 0) {
        LPTSTR buffer = new TCHAR[length + 1]; // Allocation of string
        GetWindowText(hwnd, buffer, length + 1);
        Str text(buffer);

        delete buffer; // <--- Is this line necessary?
        return text;
    } else {
        return _T("");
    }
}

我是否需要致电delete?一段时间后,我尝试使用GlobalAlloc()GlobalFree(),但在运行时我得到一个错误,说有关非法修改堆栈的事情,我没有一个确切的错误消息,因为这是一段时间以前。另外,除了你的答案之外,如果你想给我资源你发现有助于了解更多关于C ++内存管理的信息,那就太好了。

5 个答案:

答案 0 :(得分:8)

对于每个new,必须有delete,并且对于每个new[],必须有delete[]。请注意,分配有new[]的内存必须使用delete[]删除,而在发布的代码中则不是这样。

可以使用智能指针,例如boost::scoped_array,它将在其析构函数(或delete[]函数)中执行reset()。如果在调用new[]之后抛出异常:

,这将特别有用
boost::scoped_array<TCHAR> buffer(new TCHAR[length + 1]);
GetWindowText(hwnd, buffer.get(), length + 1);
Str text(buffer.get()); // buffer will be deleted at end of scope.

答案 1 :(得分:6)

您的数组已分配new[],因此必须使用delete[] delete)删除。

您的显式动态分配也是不必要的:

Str text(length+1, 0);
GetWindowText(hwnd, &text[0], length + 1);
text.resize(length); // remove NUL terminator
return text;

在C ++ 03中,需要一些理由,stringwstring实际上是否分配连续内存,适合作为缓冲区传递。它不是由C ++ 03标准保证的,但事实上它在MSVC ++中是正确的。如果你不想依赖这个事实,那么 保证了vector,所以你可以将它用于缓冲区:

std::vector<TCHAR> buffer(length+1);
GetWindowText(hwnd, &buffer[0], length + 1);
return Str(buffer.begin(), buffer.end() - 1);

在C ++中直接使用new[]是非常罕见的。在这两种情况下,我的vectorstring缓冲区都是一个自动变量,所以我不需要做任何特殊的事情来确保它的范围结束时它被正确销毁。

答案 2 :(得分:2)

是(除非您使用智能指针或类似功能将其删除)

答案 3 :(得分:2)

是的,规则很简单。您使用new分配的所有内容都需要使用delete取消分配;并且new[]分配的所有内容都需要使用delete[]取消分配。

为了减少出错的可能性,最好使用容器,智能指针或其他RAII样式的对象来管理动态资源,而不是记住自己使用delete

答案 4 :(得分:0)

当然,无论分配什么类型。它仍然有内存空间。