2015-05-16 75 views
2

假设一个包含std :: pair类型项目的std :: pair的结构体。如何使用默认值初始化std :: std :: vector对的固定长度?

block<key_t, value_t> b(*this); 
std::pair<key_t, value_t> item = std::pair<key_t, value_t>(k, v); 
b.items[0] = item; 

稍后在代码中,我要遍历向量,并期望&bucket_item != NULL是真实的,只有在:

struct block { 
    std::vector<std::pair<key_t, value_t>> items; 
    block(const Data& d) : items() 
    { 
     items = std::vector<std::pair<key_t, value_t>>(d.size_); 
    } 
}; 

代码后来,我在位置0值分配给矢量位置0,因为我只在这个位置分配了一个值。实际上,&bucket_item != NULL总是如此。

for (std::pair<key_t, value_t> item : b.items) 
{ 
    if (&item != NULL) 
    { 
     ... 
    } 
} 

我不能初始化NULL值的向量像这样:

items = std::vector<std::pair<key_t, value_t>>(d.size_, NULL); 

如何解决这个问题?

+0

'NULL'是一个指针,所以你需要做的矢量保持指向'std :: pair'的指针,并自己进行内存管理。 – jhnnslschnr

回答

3

看起来你有Java背景,C++有点不同。

items = std::vector<std::pair<key_t, value_t>>(d.size_); 

items已使用其默认构造函数初始化。上面的行创建另一个默认的初始化容器,并将其分配给items,这是不必要的。

在:

b.items[0] = item; 

你需要确保的是,载体是足够大的,因为它不operator[]分配元素为您服务。请执行b.items.push_front/back(item),或者使用vector::insert(例如)将其插入特定位置。 b.items.insert(b.items.begin(), item)push_xxxinsert确实为新元素分配内存。

当你

for (std::pair<key_t, value_t> item : b.items) 
{ 
    if (&item != NULL) 

它遍历容器中的所有现有元素。 item按容器中的值(与Java不同)存储,因此它存在于非NULL地址,并且不可能等于NULL

但是,表达式for(std::pair<key_t, value_t> item : b.items)为堆栈上的每个元素(也是非NULL地址)创建一个副本,您可能希望这是for(std::pair<key_t, value_t>& item : b.items)只是引用元素而不是复制它(注意左边的items)。如果您不打算修改循环内的item,那么您可能还想使用const限定符以向代码读者明确您的意图。例如for(std::pair<key_t, value_t> const& item : b.items)

而且由于你使用C++11无论如何,你不必拼出容器元素的类型,只要使用auto

for (auto const& item : b.items) 
    // do something to item 
+1

另外,语句'&item!= NULL'将始终为真。不仅在这个例子中,而且在任何有效的C++代码中。 – gurka

+1

只是在这里nitpicky - 如果'对'不会被修改在每个循环,我甚至会扔在'const'只是为了明确的意图的循环 – Alejandro

+0

完美,谢谢! – Scholle

0

我觉得你在这里混了几个定义。 std::vector的元素不能是NULL,因为它不是指针。并存在防御。 int arr[] = {1};,可以arr[0]为空?当然不是。为什么会这样?这是一个真正的整数,它在内存中不是空的位置。

如果你正在遍历一个std :: vector元素,这意味着它们存在,所以它们不能为null。

0

NULL,或者更好nullptr,可以被用来初始化一个指针值,但是没有意义的初始化,例如,一个或std::stringstd::pair<std::string, int>它。

如果你希望你的载体是空的,你可以使用:

std::vector<std::pair<key_t, value_t>> items; 

othwerwise,如果你想n默认构造std::pair是你可以使用:

std::vector<std::pair<key_t, value_t>> items(n); 
0

对是真的一个comination值。所以你必须定义你认为你的对的NULL值是多少的组合。

然后,您可以初始化下面的构造你的载体:

std::vector<std::pair<key_t, value_t>> items(d.size_, make_pair(0,0)) ; 

你必须与的key_t和value_t中性值替换0。

请注意,向量确实包含值,对是值。所以没有NULL指针会显示缺少值。

+0

是什么让你认为'key_t(0)'或'value_t(0)'是一个有效的表达式? – Shoe

+0

@Jefffrey这是一个插图,用适用于key_t和value_t的中性值进行adatapted。当然,10也只是所需尺寸的一个例证。 – Christophe

2

当创建具有长度len一个std::vector这样std::vector<T> tVec(len),要创建一个vectorlen默认构造T类型的对象。如果你想表示一个空值,则需要诉诸于下列方式之一:

  1. 使用的T的警戒值表示无效值。
  2. 使用(smart-)pointerT并使用nullptr作为自然无效值。
  3. 围绕T包括bool标记为无效。

最后一个选项由boost::optional提供。下面是使用它的代码的改写:

struct block { 
    using OptionalPair_t = boost::optional<std::pair<key_t, value_t>>; 
    std::vector<OptionalPair_t> items; 
    block(const Data& d) : items(d.size_) 
    { 
    } 
}; 

由于boost::optionalcontextually convertiblebool,你可以这样做:

for (auto& item : b.items) 
{ 
    if (item) 
    { 
     ... 
    } 
} 
相关问题