2009-07-02 3 views
8

Можно ли выделить произвольный блок памяти с помощью «нового» оператора? В C я могу сделать это как «void * p = malloc (7);» - это будет выделять 7 байт, если для выравнивания памяти установлено 1 байт. Как сделать то же самое в C++ с новым оператором?выделение памяти в C++

ответ

43

Произвольные блоки памяти могут быть выделены operator new в C++; а не с оператором new, который предназначен для построения объектов.

void* pBlock = ::operator new(7); 

Такие блоки могут впоследствии быть освобождены с operator delete.

::operator delete(pBlock); 

Обратите внимание, что operator new будет выделена память надлежащим образом выровненную для любого вида объекта, поэтому реализация не может выделить ровно семь байт и не более, но то же самое (обычно) относится и к malloc. Клиенты C malloc обычно нуждаются в выровненной памяти.

+7

+1 для упоминания здесь * есть способ сделать это без malloc и free :) –

+1

Также имейте в виду, что оператор new обычно просто передает доллар в malloc() в любом случае (на каждую реализацию, о которой я знаю). Как сказал Доминик, возможно, просто использовать malloc. –

+1

Большое спасибо. Это ответ («:: operator new»). Я потратил много времени, пытаясь понять, почему «:: new (x)»; не работает :) – user132349

8

Вы не можете выделить void указатель с оператором С ++ new: вам придется выделить явного типа, такие как char или uint8_t:

char *p = new char[7]; 
uint8_t *q = new uint8_t[7]; 
... 
delete [] p; 
delete [] q; 
2

Я думаю, что вы могли бы искать Placement New.

+1

Я бы добавил, что если вы собираетесь использовать такие методы, как Placement New, вы должны быть осторожны. Используйте его только в случае необходимости! –

+5

Как новое размещение относится к распределению памяти? – avakar

+0

@Miky D: Я согласен, поэтому связанная страница посыпана словом «ОПАСНОСТЬ» во всех шапках. :-) –

2

новый знак [7];

Традиционно char является байтом, хотя вы можете найти некоторые библиотеки, которые набирают тип BYTE.

+5

Не имеет значения; char - это наименьший тип, с которым может справиться реализация. Если char имеет 16 бит, тогда байтовый тип не может быть меньше 16 бит. Помните, что sizeof (char) == 1. Всегда. –

+0

@David Thornley: sizeof (char) не требуется 1, в противном случае всевозможные сортировочные библиотеки будут ужасно расстроены. – florin

+1

@florin: sizeof (char) == 1 согласно стандарту. См. Раздел 5.3.3 ИСО/МЭК 14882: 2003. «sizeof (char), sizeof (signed char) и sizeof (unsigned char) равны 1, результат sizeof, применяемый к любому другому фундаментальному типу (3.9.1), определяется реализацией». –

2

Вы можете сделать char* pBuffer = new char[7];, а так как sizeof (char) - 1 байт, вы можете использовать его в качестве байтового буфера. Кроме того, не забудьте использовать delete[] (с []) при освобождении памяти.

11

Другие ответили на вопрос как написано, но я хотел бы предложить придерживаться malloc/free для таких распределений.

новые и удаленные предназначены для выделения объектов. Они выделяют требуемую память и вызывают конструкторы/деструкторы. Если вы знаете, что вам нужен только произвольный блок памяти, использование malloc и free вполне разумно.

+1

Но если вы пишете код на C++, я думаю, что лучше использовать new/delete, так как вы будете использовать его для выделения объектов. Наличие двух типов функций выделения памяти добавляет больше путаницы. – Naveen

+1

-1. new/delete - это языковые конструкции и вводят безопасность типов независимо от того, что вы выделяете/освобождаете. malloc/free - это артефакты, оставшиеся для обратной совместимости. – sharkin

+1

@RA, если требуется произвольный общий блок байтов, нет никакой выгоды в том, чтобы полагать, что это особый символ char или unsigned или что-то еще - void * более честный и явный. +1 для malloc! –

3

Да, вы можете.
Но в зависимости от того, что вы делаете, могут быть лучшие приемы.

Можете ли вы обновить вопрос и рассказать нам, чего вы пытаетесь достичь. С большим контекстом может быть обеспечено лучшее решение.

Пример:
Если вы динамически выделяли буфер для чтения из сокета (поскольку размер не известен во время компиляции). Альтернативой будет использование векторного и динамического размера. Затем вы можете получить указатель на внутреннюю часть буфера, указав адрес первого элемента.

3

Лично я хотел бы использовать std::vector<char>. Вы не только получаете произвольный блок байтов (guaranteed to be contiguous), вы получаете их в оболочке RAII.Конечно, нет необходимости использовать какие-либо из std::vector «S методов (кроме, может быть, resize()), но нет никакого штрафа за что:

std::vector<char> buffer(7); 
void* p = &buffer[0]; 

Вы можете использовать std::string, но std::string означает«этот объект содержит символы, которые имеют смысл при распечатке », где« std::vector<char> »подразумевает« этот объект содержит произвольную группу байтов ».