2014-10-09 60 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; 
} 

这个特别节目是乖巧,但使用这种数据结构,你很可能会搬起石头砸自己的脚迟早的事。可能有更好的解决方案。