winapi — память C ++. Нужно ли удалять переменные примитивного типа, созданные с помощью ‘new’?

Я новичок, когда дело доходит до управления памятью в C ++. Я читал, что если вы создаете класс с new ключевое слово, которое вы должны delete объект, чтобы освободить свою память. Я также читал, что примитивные типы, такие как int, char а также bool, создаются в стеке, что означает, что они удаляются при выходе из области видимости.

Но как насчет примитивных типов, созданных с new ключевое слово? Нужно ли явно звонить delete? Они созданы в куче как классы? Или, поскольку они примитивны, они все еще создаются в стеке?

Я спрашиваю, потому что я выделяю 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 ++, это было бы неплохо.

0

Решение

Ваш массив выделен с new[] и, следовательно, должны быть удалены с delete[] (не delete).

Ваше явное динамическое распределение также не нужно:

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

В C ++ 03 есть какое-то обоснование, string а также wstring фактически выделяем непрерывную память, пригодную для передачи в качестве буфера. Это не гарантируется стандартом C ++ 03, но на самом деле это верно для MSVC ++. Если вы не хотите полагаться на этот факт, то это является гарантировано для вектора, так что вы можете использовать это для буфера:

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

Прямое использование довольно редко new[] в C ++. В обоих случаях мой vector или же string Буфер является автоматической переменной, поэтому мне не нужно делать ничего особенного, чтобы убедиться, что он уничтожен правильно, когда заканчивается его область действия.

6

Другие решения

Для каждого 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.
8

ДА (если вы не используете умные указатели или аналогичные, чтобы удалить его для вас)

2

Да, правило очень простое. Все, что вы выделяете new должен быть освобожден с delete; и все выделено new[] должен быть освобожден с delete[],

Чтобы уменьшить вероятность ошибки, лучше всего использовать контейнеры, умные указатели или другие RAII-объекты стиля для управления динамическими ресурсами, а не для использования delete сам.

2

Конечно, независимо от того, какой тип был выделен. Это все еще имеет место в памяти.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector