针对resize()+迭代器的循环push_back

时间:2008-12-19 15:25:43

标签: c++ stl

简单的问题;什么更好,为什么?



    out.resize( in.size() );
    T1::iterator outit = out.begin();
    for( inIt = in.begin() to end, ++inIt, ++outIt )
       *outit = *inIt
OR

    out.erase();
    for( inIt = in.begin() to end, ++inIt )
        out.push_back( inIt );


我假设push_back中隐含的内存赋值值得避免,但想确定。

由于

编辑: 感谢out = in advice guys;)。我正在玩的实际代码是:


template//can't stop the browser ignoring th class T1, class T2 in angle brackets
bool asciihex( T1& out, const T2& in )
{
    //out.erase();
    out.resize( in.size() / 2 );
    if( std::distance( in.begin(), in.end() ) % 2 )//use distance rather than size to minimise the requirements on T2?
        return false;
    for( T2::const_iterator it = in.begin(); it != in.end(); it += 2 )
    {
        out.push_back(((( (*it > '9' ? *it - 0x07 : *it)  - 0x30)  '9' ? *(it+1) - 0x07 : *(it+1)) - 0x30) & 0x000f));
    }
    return true;
}

template
bool asciihex( T1& out, const T2& in )
{
    size_t size = in.size();
    if( size % 2 )//use distance rather than size to minimise the requirements on T2?
        return false;
    out.resize( size / 2 );
    T1::iterator outit = out.begin();
    for( T2::const_iterator it = in.begin(); it != in.end(); it += 2, ++outit )
    {
        *outit = ((( (*it > '9' ? *it - 0x07 : *it)  - 0x30)  '9' ? *(it+1) - 0x07 : *(it+1)) - 0x30) & 0x000f);
    }
    return true;
}

编辑:我已将push_back标记为答案,因为它似乎是共识,因此对于遇到同样问题的其他人更有用。但是我最终使用迭代器方法作为我感兴趣的容器类之一,不支持push_back ...里程各不相同。

8 个答案:

答案 0 :(得分:4)

第二个,如果你担心多个扩展,请使用out.reserve()。添加到向量的正确答案几乎总是push_back或back_inserter,这可以避免一些可能的问题(异常保证,构造函数,例如,在结束时编写),而其他方法必须注意这些问题。

答案 1 :(得分:2)

第二个,只要你先保留正确的容量。

我看到的一个问题(除了样式)是在第一个问题中,如果您的复制作业被抛出,您已经采取了一项操作,该操作应该给您强有力的保证,并且用它来做出保证。

答案 2 :(得分:2)

如果您关心保留in,请执行:

out = in;

如果不这样做,请执行:

std::swap(out, in);

如果out和in是不同类型的容器,那么试试这个:

out.erase(out.begin(), out.end());
// if it's a vector or other contiguous memory container, you'll want to reserve first
// out.reserve(in.size());
std::copy(in.begin(), in.end(), back_inserter(out));

答案 3 :(得分:1)

这有什么问题?

out = in;

难道你不认为这有最好的行为吗?如果没有,那很糟糕。

此外,您的两个代码示例应该是

out.resize( in.size() );
T1::iterator outIt = out.begin();
for( T1::iterator inIt = in.begin(); inIt != in.end(); ++inIt, ++outIt )
   *outIt = *inIt;

out.erase(out.begin(), out.end());
for( T1::iterator inIt = in.begin(); inIt != in.end(); ++inIt )
    out.push_back( *inIt );

答案 4 :(得分:1)

如果你正在处理像整数或双精度这样的简单值,那么如果你调整大小并设置或保留和推回,则无关紧要(性能明智)。

如果您正在处理具有重要构造函数的更复杂对象,最好使用第二个基于push_back的方法。

如果对象没有有意义的默认构造函数,则push_back方法是唯一有效的方法。

答案 5 :(得分:1)

我遇到的情况是,在基于push_back的解决方案中,与在调整大小的向量上使用[]运算符的解决方案相比,我的性能更差。差异的原因是每次执行push_back时检查向量是否需要扩展其容量的开销。

更糟糕的是,编译器决定无法内联对push_back的调用,但它确实将保留逻辑内联到push_back方法中。这给了函数调用的开销,并且调用的函数是不必要的。即使经过一些force_inline按摩,它也不如基于[]运算符的循环快。

基于迭代器或[]运算符的循环除了写入值之外不会做任何事情,至少在处理简单类型时不会这样做。如果使用更高级的类型,调整向量大小时默认构造函数的成本可能会破坏潜在的胜利。

无论如何,如果你的程序大部分时间花在这种循环上我绝对认为你应该对不同的解决方案进行基准测试,看看是否有任何性能可以通过使用其中一个解决方案获得。如果你没有在你描述的功能上花费大量的执行时间,你不应该关心这篇文章:)

答案 6 :(得分:0)

之前曾讨论here类似的东西。

答案 7 :(得分:0)

我更喜欢push_back而不是数组赋值,因为push_back可以使用或不使用randomaccessiterator。数组赋值需要它们。如果您现在强制使用randomaccessiterator,将来无法轻松更改容器。当然,为了避免调整大小问题,可以调用vector :: capacity而不是resize。