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

Bra*_*ler 0 c++ memory winapi memory-management allocation

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

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

我问,因为我正在LPTSTR使用new关键字分配一个,但是我担心如果我不调用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("");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

hmj*_*mjd 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.
Run Code Online (Sandbox Code Playgroud)


Ste*_*sop 6

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

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

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

在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);
Run Code Online (Sandbox Code Playgroud)

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