2014-10-09 35 views
0

我希望能夠創建一個固定長度的容器(vectordeque?)作爲一個緩衝區,然後給另一個對象的向量指針的位置的指針緩衝區中,讓他們在寫。使用指針寫入標準容器

例如(不是可編譯代碼)

class Item { 
    *p //pointer to a place in the vector 
    vector<int> values 
} 

vector<Item> items; 

for(auto item : items) { 
    for(auto value : values) { 
    buffer[p] = item->value 
    ++(item->p); 
    } 
} 

但是,我不知道如何讓關係,其中很明顯每個Item,他們應該開始寫緩衝區。

我應該注意,對於每次迭代items,最終緩衝區都有一個已知的固定大小 - 但在函數調用之間,Items的數量可能會改變。

感謝,

+0

你的意思是一樣的std ::陣列? – stonemetal 2014-10-09 20:48:05

+0

我不認爲'的std :: array'會的工作,因爲每次迭代在我的項目,最後的緩衝區大小是已知的,但功能之間的呼叫'items'可以改變大小。我也不知道如何給每個'Item'一個指向它應該開始寫的地方的指針。 – 2014-10-09 20:51:22

+0

'然後用指針來有項目寫入向量的某些部分如果被矢量調整創造buffer',你所設置的指針最終可能指向垃圾,因爲一個矢量的迭代器變得無效。 – PaulMcKenzie 2014-10-09 20:54:49

回答

2

我應該注意,每次迭代在items,最終緩衝區具有已知的固定尺寸 - 但之間的函數調用的Items數量可能會改變。

正如我在評論,指針和引用的規定,你會採取和跟蹤包含在std::vector<whatever>價值並不穩定,只要載體是允許由push_back()erase()或其他任何改變這種操作。


雖然,你有選擇,

  • 參考向量的索引。這些將是穩定的,即使std::vector<>需要重新分配和複製。

  • 使用smart pointersstd::unique_ptr<>std::shared_ptr<>存儲在std::vector<>而不是實例副本。

這完全取決於你的實際使用情況,這是正確的方式去。

4

如果我正確地理解了這個問題(我不確定),你應該使用索引而不是指針或迭代器,因爲它是一個相對於緩衝區開始的偏移量,而不是絕對地址將被緩衝區的更改無效。

class Item 
{ 
    size_t pos; // index into the buffer 
    vector<int> values; 
}; 

vector<Item> items; 
// ... 
std::vector<int> buffer; 
buffer.resize(N); 
for (auto& item : items) 
{ 
    assert(buffer.size() >= (item.pos + item.values.size())); 
    std::copy(std::begin(item.values), std::end(item.values), 
      std::begin(buffer)+item.pos); 
} 

這將無論是vectordeque的緩衝區(或任何其他與RandomAccessIterators)工作,但你似乎並不需要在緩衝區的開頭添加/移除元素(只調整它曾經並分配給現有的元素),那麼沒有理由使用矢量,這通常應該是你的容器的默認選擇,除非你需要其他容器的特定特性。

我不知道您打算如何設定Item::pos值,也許這將是有意義:

size_t pos = 0; 
for (auto& item : items) 
{ 
    item.pos = pos; 
    pos += item.values.size(); 
    assert(buffer.size() >= pos); 
    std::copy(std::begin(item.values), std::end(item.values), 
      std::begin(buffer)+item.pos); 
} 

這將使每個項目依次進入緩衝區,並記錄在飛行的位置。

這甚至可以在不預先知道總的緩衝區大小工作,根據需要調整緩衝:

size_t pos = 0; 
for (auto& item : items) 
{ 
    item.pos = pos; 
    pos += item.values.size(); 
    if (buffer.size() < pos) 
    buf.resize(pos); 
    std::copy(std::begin(item.values), std::end(item.values), 
      std::begin(buffer)+item.pos); 
} 

因爲你存儲的索引,而不是一個絕對地址,它會繼續工作即使在緩衝區被調整大小並且其內容被重新定位到不同的內存塊之後。

0

正如其他人已經評論,我不知道你想什麼來實現,但你原來的代碼是不是遠離的東西,可以被編譯並已明確的(儘管沒有用處)行爲。

我想你可能已經打算寫:

#include <vector> 
#include <iostream> 

struct Item 
{ 
    std::vector<int>::iterator p; 
    std::vector<int> values; 

    Item() : values {'H', 'A', 'P', 'P', 'Y'} 
    { 
    this->p = values.begin(); 
    } 
}; 

std::ostream& 
operator<<(std::ostream& os, const Item& item) 
{ 
    os << "["; 
    for (std::size_t i = 0; i < item.values.size(); ++i) 
    os << (i ? ", " : "") << item.values.at(i); 
    os << "]"; 
    return os; 
} 

int main() 
{ 
    std::vector<Item> items {4}; 
    for (auto& item : items) 
    { 
     for (auto value : item.values) 
     { 
      *(item.p) = value; // Note: self-assignment with no effect 
      ++(item.p); 
     } 
    } 
    for (auto& item : items) 
    std::cout << item << std::endl; 
} 

這個特別節目是乖巧,但使用這種數據結構,你很可能會搬起石頭砸自己的腳遲早的事。可能有更好的解決方案。