[英]How can I allocate memory for the std::vector<std::vector<int> > data type?
[英]How can I allocate memory for a data structure that contains a vector?
如果我有一個struct instanceData:
struct InstanceData
{
unsigned usedInstances;
unsigned allocatedInstances;
void* buffer;
Entity* entity;
std::vector<float> *vertices;
};
而且我為Entity和std :: vector分配了足夠的內存:
newData.buffer = size * (sizeof(Entity) + sizeof(std::vector<float>)); // Pseudo code
newData.entity = (Entity *)(newData.buffer);
newData.vertices = (std::vector<float> *)(newData.entity + size);
然后嘗試向其復制任何大小的向量:
SetVertices(unsigned i, std::vector<float> vertices)
{
instanceData.vertices[i] = vertices;
}
我收到訪問沖突讀取位置錯誤。
我已經精簡了代碼,以使其簡潔明了,但這是基於Bitsquid的ECS的 。 因此,只要我不處理向量就假設它可以工作(確實可以)。 考慮到這一點,我假設它有問題,因為它不知道向量將縮放到多大。 但是,我認為向量可能會沿着另一個維度增加,像這樣嗎?:
我錯了嗎? 無論哪種方式, 如何在這樣的緩沖區中為矢量分配內存 ?
是的, 我知道向量可以管理自己的內存 。 那不是重點。 我正在嘗試做不同的事情。
看起來您想讓InstanceData.buffer具有由其他事物分配/釋放/訪問的實際內存空間。 然后,實體和頂點指針指向該空間。 但是,通過嘗試使用std :: vector,您正在混淆兩種完全不兼容的方法。
1)您可以使用語言和標准庫來執行此操作,這意味着沒有原始指針,沒有“新”,沒有“ sizeof”。
struct Point {float x; float y;} // usually this is int, not float
struct InstanceData {
Entity entity;
std::vector<Point> vertices;
}
這就是我推薦的方式。 如果您需要輸出為特定的二進制格式進行序列化,只需在save方法中進行處理即可。
2)您可以使用oldschool C管理班級內部的內存,這意味着對頂點使用N * sizeof(float)。 由於這對於新程序員來說非常容易出錯(對於獸醫來說仍然很困難),因此您必須將所有這些私有化以用於InstanceData類,並且不允許InstanceData之外的任何代碼來管理它們。 使用單元測試。 提供公共獲取功能。 對於通過網絡傳輸的數據結構,或在讀取/寫入具有指定格式(Tiff,pgp,z39.50)的文件時,我已經做了類似的工作。 但是僅使用困難的數據結構存儲在內存中就沒有辦法。
您提出了其他一些問題:
如何為std :: vector分配內存?
你不知道 向量分配自己的內存,並對其進行管理。 您可以告訴它resize()或reserve()空間或push_back,但它將處理它。 看看http://en.cppreference.com/w/cpp/container/vector
我如何在這樣的緩沖區中為向量[sic]分配內存?
您似乎在考慮數組。 到目前為止,您的偽代碼還很遙遠,因此您確實需要逐步學習本教程。 您必須使用“新”進行分配。 如果您確實需要,我可以為此發布一些入門代碼,我將在此處將其編輯為答案。
此外,您還談到了向量在另一個維度上增加的問題。 向量是一維的。 您可以將向量設為向量,但讓我們不要討論。
編輯附錄:
兆緩沖區的基本思想是,在緩沖區中分配所有必需的空間,然后初始化值,然后通過吸氣劑使用它。
數據布局為“標題,實體1,實體2,...,實體N”
// I did not check this code in a compiler, sorry, need to get to work soon
MegaBuffer::MegaBuffer() {AllocateBuffer(0);}
MegaBuffer::~MegaBuffer() {ReleaseBuffer();}
MegaBuffer::AllocateBuffer(size_t size /*, whatever is needed for the header*/){
if (nullptr!=buffer)
ReleaseBuffer();
size_t total_bytes = sizeof(Header) + count * sizeof(Entity)
buffer = new unsigned char [total_bytes];
header = buffer;
// need to set up the header
header->count = 0;
header->allocated = size;
// set up internal pointer
entity = buffer + sizeof(Header);
}
MegaBuffer::ReleaseBuffer(){
delete [] buffer;
}
Entity* MegaBuffer::operator[](int n) {return entity[n];}
標題始終是固定大小,並且僅出現一次,並告訴您您有多少個實體。 在您的情況下,沒有標題,因為您使用的是成員變量“ usedInstances”和“ allocatednstances”。 因此,您確實有一個標頭,但它不是分配的緩沖區的一部分。 但是,您不想分配0字節,因此只需將usedInstances = 0設置為即可; locatedInstances = 0; buffer = nullptr;
我沒有編寫更改緩沖區大小的代碼,因為bitsquid ECS示例涵蓋了這一點,但是他沒有顯示首次初始化。 使用它們之前,請確保初始化n並分配它們,並為每個實體分配有意義的值。
您所執行的bitsquid ECS與發布的鏈接不同。 在這種情況下,他在並行數組中有幾個固定大小的不同對象。 存在一個實體,其質量,位置等。因此,entity [4]是質量等於“ mass [4]”且其加速度為“ acceleration [4]”的實體。 這使用指針算法來訪問數組元素。 (內置在數組中,不是std :: Array,不是std :: vector)
數據布局為“ Entity1,Entity2,...,EntityN,mass1,mass2,...,massN,position1,position2,...,positionN,velocity1 ...”,您就會明白。
如果您閱讀該文章,您會發現他對其他人所說的關於標准庫的說法基本相同。 您可以使用std容器存儲這些數組中的每個數組,或者可以分配一個兆緩沖區,並使用指針和“內置數組”數學方法來獲取每個條目在該緩沖區中的確切內存位置。 在經典的假裝舞步中,他甚至說:“這避免了Array類中可能存在的任何隱藏開銷,並且我們只有一個分配即可跟蹤。” 但是您不知道它是比std :: Array更快還是更慢,並且您引入了很多錯誤和額外的開發時間來處理原始指針。
我想我明白了您要做什么。
有很多問題。 第一。 您正在建立一個隨機數據的緩沖區,告訴C ++它的Vector大小是Vector。 但是,您實際上從來沒有真正將構造函數調用為Vector,它將初始化指針並將其內部構造為可行的值。
這已在此處得到解答: 在已分配的內存上調用構造函數
第二個問題是線
instanceData.vertices[i] = vertices;
instanceData.vertices是指向Vector的指針,因此您實際上需要編寫
(*(instanceData.vertices))[i]
第三個問題是*(instanceData.vertices)的內容是浮點數,而不是Vector,因此您不能在那里進行賦值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.