Предположим, мне нужен массив с переменным размером с бит заголовка вверх, хранящийся в std::shared_ptr
. Я мог бы сделать что-то вродеОбъект с переменным размером в shared_ptr
#include <memory>
using namespace std;
struct obj {
char headerCode;
unique_ptr<short[]> data;
};
shared_ptr<obj> make(unsigned len) {
return shared_ptr<obj>{new obj{'x', unique_ptr<short[]>{new short[len]}}};
}
Но это привело бы к трем распределений: один для блока shared_ptr
управления, один для obj
и один для его data
. С make_shared
возможно, что первые два разделяют некоторую память:
#include <memory>
using namespace std;
struct obj {
char headerCode;
unique_ptr<short[]> data;
obj(char headerCode, short data[]) : headerCode(headerCode), data(data) {}
};
shared_ptr<obj> make(unsigned len) {
return make_shared<obj>('x', new short[len]);
}
С выделением низкого уровня, я могу сделать объект и его доля данных некоторую память:
#include <memory>
#include <cstdlib>
using namespace std;
struct obj {
char headerCode;
short data[0];
};
shared_ptr<obj> make(unsigned len) {
obj* o = reinterpret_cast<obj*>(malloc(sizeof(obj) + len*sizeof(short)));
o->headerCode = 'x';
return shared_ptr<obj>(o, free);
}
Являются ли эти два метода, допускаемые стандарт? Если нет, есть ли что-то подобное, что разрешено? Есть ли что-то, что заставляет эту работу соответствовать стандартам со всего лишь одним распределением памяти? Предпочтительно без необходимости хранить распределитель или удалять объект в каждом экземпляре?
Зачем использовать 'reinterpret_cast' для преобразования' void * 'в' obj * '? –
@JonathanWakely: без явного приведения my 'g ++' говорит 'error: недопустимое преобразование из 'void *' в 'obj *' [-fpermissive]'. Но вы правы, «static_cast», вероятно, более уместен. – MvG
Да, конечно, он не будет конвертировать неявно, но 'reinterpret_cast' является кувалдой, здесь это не обязательно. 'static_cast' - это все, что нужно. –