将2d向量的值设置为0的快速方法

时间:2015-04-17 10:03:14

标签: c++ vector

给出以下示例

#include <iostream>
#include <vector>
#include <algorithm>
#include<iterator>

using namespace std;

template<typename T>
ostream& operator<<(ostream& os, const vector<T>& v){
    copy(v.begin(), v.end(), ostream_iterator<T>(os, "  "));
    return os;
}


int main (){

vector<int>vec;
vector<vector<int>> x(10,vector<int>());
for(int i=0; i< x.size(); i++)
    x[i].resize((rand() % 100 + 1), 10);

for(int i=0; i< x.size(); i++)
    fill(x[i].begin(),x[i].end(),0);

return 0;
}

将第二个向量中的值设置为0

的最快方法是什么

日Thnx

4 个答案:

答案 0 :(得分:5)

完全没必要用零填充内部std::vector,因为resize默认 - 将新元素插入到值初始化它们的向量中。在int s的情况下,值初始化意味着将它们设置为0.


从标准中确定这一点可能有点困难,所以这里的路径(来自N4296 - C ++ 14草案):

resize

的定义
  

如果size() < sz,请将sz - size()默认插入的元素附加到序列中。

default-inserted的定义:

  

X的元素如果通过评估表达式

进行初始化,则默认插入
allocator_traits<A>::construct(m, p)
     

其中pX内分配的元素的未初始化存储的地址[和mA类型的分配器。

allocator_traits<A>::construct的定义:

template <class T, class... Args>
static void construct(Alloc& a, T* p, Args&&... args);
     

效果:如果调用格式良好,则调用a.construct(p, std::forward<Args>(args)...);否则,[...]。

从分配器的定义:

a.construct(c, args)
     

效果:构造一个对象   在c

处键入C.      

默认值:::new ((void*)c) C(forward<Args>(args)...)

new - 表达式的定义:

  
      
  • 如果省略new-initializer,[...]

  •   
  • 否则,新的初始化程序将根据8.5的初始化规则进行解释,以进行直接初始化。

  •   

从直接初始化的定义:

  
      
  • [...]

  •   
  • 如果初始值设定项为(),则对象进行值初始化。

  •   
  • [..]

  •   

值初始化:

  
      
  • 如果T是[...];
  • 的(可能是cv认证的)类类型   
  • 如果T是[...];
  • 的(可能是cv认证的)类类型   
  • 如果T是数组类型,那么[...];
  •   
  • 否则,该对象为零初始化。
  •   

零初始化:

  
      
  • 如果T是标量类型(3.9),则将对象初始化为通过将整数0(零)转换为T获得的值;

  •   
  • 如果[...]

  •   

答案 1 :(得分:1)

在您的示例中,最初使用零初始化向量是最简单和最快速的。在父矢量的构造函数中,如果它们的长度相同,或者在调整大小时,如果矢量是随机长度。

如果你有一个带有旧值的向量的现有向量,并且你想将它们全部设置为零,那么memset通常是最快的方法。由于向量保证具有连续存储,并且内部向量不包含复杂(非POD)对象,因此使用memset

是安全的
for(auto& v : x)
    std::memset(&v[0], 0, sizeof(v[0]) * v.size());

也就是说,std::fill_nstd::fill 可能可能同样快,并且不仅限于POD /内置对象,而且更易于阅读,因此我建议使用它。如果您遇到瓶颈,请查看您的代码,看看您是否在目标平台上获得了memset的任何内容。否则,坚持你所拥有的。

答案 2 :(得分:1)

在C ++ 11中

for (auto &i : x)
    std::fill(i.begin(), i.end(), 0);

或(在C ++ 11之前)

for (std::vector<int>::iterator i=x.begin(), end = x.end(); i != end; ++i)
    std::fill(i.begin(), i.end(), 0);

将难以击败 - 并且可能会使用索引击败循环(如x[i]中所示)。

答案 3 :(得分:0)

使用接受初始值的vector :: vector(count,value)构造函数。在下面的例子中,它将被设置为零。

vector< vector<int> > yourVector(value1, vector<int>(value2)); 

// initial value will be zero